What are the best practices to dynamically create views and add controls to view using MVVM pattern
Can anyone give out the best practices for playing around with controls at runtime such as creating a new view,adding views inside a view,adding contr开发者_如何学编程ols to containers using MVVM pattern without breaking mvvm pattern??
I am using MVVMlight toolkit..
please help me out in this regard..
Thanks in advance......
This post discusses the strategies for creating views (dialogs) from your view models.
Edit:
From your comment I take it that you got an user interface that has an add and delete button. The add button should add an item (type ?) to a ItemsControl
... hope that's correct.
So, how would I do this, well I would create a view model that has an ObservableCollecion<ItemViewModel>
. The ItemViewModle
is the view mode that represents the item that should be added to the ItemsControl
(so in your case the view model backing your "rangeView").
Then I would add two commands that handle the addition and deletion of items. Both commands just add/remove ItemViewModels
from your collection.
To show the items in the view I would bind the ItemControl.ItemsSource
property to the collection in your main view model (i.e. the one holding the ItemViewModel
instances). The I would supply an ItemTemplate to render the items on the screen.
Ok, here is an example of what I think you are trying to do (at least conceptionally). Complete Source Code here. In the example I used a ListBox as it allows me easily to determine which item is selected, this depends on your szenario. Also note that you have complete freedom to customize the Template, the ItemPanelTemplate, and DataTemplate to fit your needs. You can even use this approacht to create PanoramaPages in WP7!
2nd edit: ItemsControl
does not have a SelectedItem
property. To get to it you have to use a control inheriting from Selector
(e.g. a ListBox as I did) or you can use the Selector
directly.
ItemViewModel:
public class ItemViewModel : ViewModelBase
{
#region [Name]
public const string NamePropertyName = "Name";
private string _name = null;
public string Name {
get {
return _name;
}
set {
if (_name == value) {
return;
}
var oldValue = _name;
_name = value;
RaisePropertyChanged(NamePropertyName);
}
}
#endregion
}
MainViewModel:
public class MainViewModel : ViewModelBase
{
public MainViewModel() {
if (IsInDesignMode) {
this.Items = new ObservableCollection<ItemViewModel>(Enumerable.Range(0, 10).Select((x, i) => new ItemViewModel() { Name = "Design Time Item " + i }));
} else {
// Code runs "for real"
}
}
#region [AddCommand]
private RelayCommand _addCommand;
public RelayCommand AddCommand {
get {
return _addCommand ?? (_addCommand = new RelayCommand(
() => {
this.Items.Add(new ItemViewModel() { Name = "New item - " + DateTime.Now });
}
));
}
}
#endregion
#region [DeleteCommand]
private RelayCommand _deleteCommand;
public RelayCommand DeleteCommand {
get {
return _deleteCommand ?? (_deleteCommand = new RelayCommand(
() => {
this.Items.Remove(this.SelectedItem);
},
() => { return this.SelectedItem != null; }
));
}
}
#endregion
#region [Items]
public const string ItemsPropertyName = "Items";
private ObservableCollection<ItemViewModel> _items = new ObservableCollection<ItemViewModel>();
public ObservableCollection<ItemViewModel> Items {
get {
return _items;
}
set {
if (_items == value) {
return;
}
var oldValue = _items;
_items = value;
RaisePropertyChanged(ItemsPropertyName);
}
}
#endregion
#region [SelectedItem]
public const string SelectedItemPropertyName = "SelectedItem";
private ItemViewModel _selectedItem = null;
public ItemViewModel SelectedItem {
get {
return _selectedItem;
}
set {
if (_selectedItem == value) {
return;
}
var oldValue = _selectedItem;
_selectedItem = value;
RaisePropertyChanged(SelectedItemPropertyName);
// important in SL to notify command that can execute has changed !
this.DeleteCommand.RaiseCanExecuteChanged();
}
}
#endregion
}
MainPage.xaml
<UserControl
x:Class="MvvmLight1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Height="300"
Width="300"
DataContext="{Binding Main, Source={StaticResource Locator}}"
>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<!-- we are dealing with ItemViewModels now -->
<Border BorderThickness="0,0,0,1" BorderBrush="Gray" Padding="10,5">
<TextBlock Text="{Binding Name}"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Margin="5,10" Content="Add" Command="{Binding AddCommand}" Width="70"/>
<Button Margin="5,10" Content="Delete" Command="{Binding DeleteCommand}" Width="70"/>
</StackPanel>
</Grid>
</UserControl>
精彩评论