我正在尝试为mt WPF应用程序实现MVVM设计模式。为了将视图连接到视图模型,我使用ResourceDictionary
(在Application.Resources
中使用),看起来像
<DataTemplate DataType={x:Type viewmodel:SampleViewModel}>
<view:SampleView1 />
</DataTemplate>
然后将视图模型简单地放入内容演示者中以显示它们。
现在,当用户按下按钮时,我想使用不同的视图显示SampleViewModel
。如何更改用于SampleViewModel
的数据模板?
答案 0 :(得分:9)
少说更多代码。
据你所说,你有班级SampleViewModel
。我添加了属性Title
用于演示,ViewType
用于标识正确的视图:
public enum ItemViewType { View1, View2 };
public class SampleViewModel
{
public string Title { get; set; }
public ItemViewType ViewType { get; set; }
}
两个视图的DataTemplateSelector
取决于ViewType
属性:
class ItemViewTemplateSelector : DataTemplateSelector
{
public DataTemplate View1Template { get; set; }
public DataTemplate View2Template { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var vm = item as SampleViewModel;
if (vm == null)
return null;
switch (vm.ViewType)
{
case ItemViewType.View1:
return View1Template;
case ItemViewType.View2:
return View2Template;
}
return null;
}
}
Xaml代码:
<Window.Resources>
<DataTemplate x:Key="view1Template">
<TextBlock Text="{Binding Title}" Foreground="Red"/>
</DataTemplate>
<DataTemplate x:Key="view2Template">
<TextBox Text="{Binding Title}" />
</DataTemplate>
<local:ItemViewTemplateSelector x:Key="viewTemplateSelector"
View1Template="{StaticResource view1Template}"
View2Template="{StaticResource view2Template}"/>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<StackPanel>
<Button Content="ChangeView" HorizontalAlignment="Center" Command="{Binding SwitchViewCommand}"/>
<ContentControl Content="{Binding ItemViewModel}" ContentTemplateSelector="{StaticResource viewTemplateSelector}"/>
</StackPanel>
主要部分在班级MainViewModel
中,我已经把逻辑用于切换视图:
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
this.ItemViewModel = new SampleViewModel { Title = "Some title", ViewType = ItemViewType.View1 };
this.SwitchViewCommand = new RelayCommand(() =>
{
this.ItemViewModel.ViewType = this.ItemViewModel.ViewType == ItemViewType.View1
? ItemViewType.View2
: ItemViewType.View1;
//The magic senquence of actions which forces a contentcontrol to change the content template
var copy = this.ItemViewModel;
this.ItemViewModel = null;
this.ItemViewModel = copy;
});
}
public RelayCommand SwitchViewCommand { get; set; }
private SampleViewModel itemViewModel;
public SampleViewModel ItemViewModel
{
get { return itemViewModel; }
set
{
itemViewModel = value;
RaisePropertyChanged("ItemViewModel");
}
}
}
SwitchViewCommand
可以是任何类型的命令,我使用mvvmlight库中的命令。
在命令的处理程序中,我更改了viewmodel的类型并以一种棘手的方式更新属性ItemViewModel
,因为ContentControl
仅在更改Content属性时刷新视图,并且此属性将除非您设置对不同对象的引用,否则不得更改。
我的意思是,即使代码this.ItemViewModel = this.itemViewModel
也不会更改视图。
这很奇怪,但解决方法并不需要太多工作。
答案 1 :(得分:1)
您可以通过在树中放置较低的类似资源来覆盖映射。由于WPF将通过向上搜索来解析资源,因此这种覆盖将替换您现有的映射。
答案 2 :(得分:1)
您可以通过多种不同的方式实现这一目标,具体取决于您想要的架构。