在主视图中,我有预览部分,它根据用户的操作显示上下文数据(即通过与某些控件交互,显示一些预览部分)。视图是否应该包含 XAML 中所有可能的预览,然后显示/隐藏/更新?ViewModel 是否应该具有由 ViewModel 的内部状态机设置的“public bool ShowPreviewA”和“public bool ShowPreviewB”之类的属性?
不,当然不是,如果这些“预览”是完全不同的 UI,具有完全不同的数据,那么使用DataTemplates
.
例如:
给定一些类:
public class Person: BusinessEntity //BusinessEntity is just a fictional base class for Model classes
{
public string LastName {get;set;}
}
public class Product: BusinessEntity
{
public string ProductName {get;set;
}
假设您的 ViewModel 定义如下:
public class SomeViewModel: ViewModelBase //Same comment as above
{
public BusinessEntity SelectedEntity {get;set;} //NotifyPropertyChanged() etc
}
您的 XAML 可以这样定义:
<Window ...>
<Window.Resources>
<!-- DataTemplate for Person class -->
<DataTemplate DataType="Person">
<TextBox Text="{Binding LastName}"/>
</DataTemplate>
<!-- DataTemplate for Product class -->
<DataTemplate DataType="Product">
<TextBox Text="{Binding ProductName}"/>
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding SelectedEntity}"/>
</Window>
WPF 将负责根据ViewModel中的属性中放置的对象类型来呈现适当DataTemplate
的内部。ContentPresenter
SelectedEntity
当某些控件之间存在复杂的交互时,逻辑应该在哪里。例如,通过防止取消选中,必须选择至少一个必须选中的 3 个复选框。在我看来,一方面它会污染 ViewModel,另一方面也感觉对 View 有一定的“知识”。
您可以轻松地继承ObservableCollection<T>
以可重用的方式创建此逻辑。然后在您的 ViewModel 中放置一些public SelectableCollection<T> MyItems {get;set;}
选择/互斥等由等处理的SelectableCollection
位置。
底线:MVVM 是关于可重用性和功能封装的。