更改ViewModel的视图
我正在尝试为mt WPF应用程序实现MVVM设计模式。 为了将视图连接到视图模型,我使用ResourceDictionary
(在Application.Resources
),看起来像
然后将视图模型简单地放入内容演示者中以显示它们。
现在,当用户按下按钮时,我想使用不同的视图显示SampleViewModel
。 如何更改SampleViewModel
使用的数据模板?
少说更多的代码。 就你所说,你有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代码:
主要部分是在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
也不会改变视图。 这很奇怪,但解决方法并不需要太多工作。
您可以通过多种不同方式实现此目标,具体取决于您想要的架构。
- 您可以编写自定义DataTemplateSelector并在ContentControl.ContentTemplateSelector上使用它并适当地选择这两个模板
- 如果这种改变视图的模式发生在许多不同的地方和更频繁的UX,我还建议使用基于SampleViewModel中的属性的DataTemplate.DataTrigger切换这两个视图[我猜你可能在ViewModel中有一个区别属性知道那个州]
您可以通过在树中放置较低的类似资源来覆盖映射。 由于WPF将通过向上搜索来解析资源,因此这种覆盖将替换您现有的映射。