如何设计一个考虑MVVM最佳实践的视图

时间:2013-07-05 19:44:31

标签: wpf mvvm

这个问题是关于如何考虑MVVM的应用程序设计。我理解MVVM的一般概念(ViewModel不知道View,Models代表域对象等等)。我也知道命令以及一些控件如何在ViewModel上调用命令。

我无法弄清楚的是如何将真实应用程序纳入此模型(与简单的文本框/按钮/查询数据库示例相对)。以下是一些问题:

  • 在主视图中,我有预览部分,根据用户的操作显示上下文数据(即通过与某些控件交互,显示一些预览部分)。视图是否应包含XAML中的所有可能的预览,然后显示/隐藏/更新? ViewModel是否应具有ViewModel内部状态机设置的“public bool ShowPreviewA”和“public bool ShowPreviewB”等属性?
  • 当某些控件之间存在复杂的交互时,逻辑应该存在于何处。例如,通过阻止取消选中,必须选中至少一个的3个复选框。在我看来,它一方面会污染ViewModel,另一方面也觉得有关于View的某些“知识”。

这个问题难以正确表达(如果可以的话,我可能会更好地理解MVVM)。

欢迎任何提示。

修改: 真正的问题是如何在编写ViewModel的功能时解决问题。它是自上而下的组合 - 即在ViewModel属性中编码每个可能的View状态 - 以及自下而上 - 即每个逻辑相关的控件集从子ViewModels接收它们的属性,这些属性报告“向上”一些逻辑状态(例如有效输入) ?

1 个答案:

答案 0 :(得分:1)

  

在主视图中,我有预览部分,显示上下文数据   取决于用户正在做什么(即通过与某些人进行交互)   控件,显示一些预览部分)。视图是否应包含所有内容   XAML中可能的预览,然后显示/隐藏/更新?应该是ViewModel   拥有“public bool ShowPreviewA”和“public bool”等属性   ShowPreviewB“由ViewModel的内部状态机设置?

不,当然不是,如果这些“预览”是完全不同的具有完全不同数据的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将负责在DataTemplate内呈现适当的ContentPresenter,具体取决于ViewModel中SelectedEntity属性中放置的对象类型。


  

当某些控件复杂时,逻辑应该存在于何处   他们之间的互动。例如,至少有3个复选框   必须通过阻止取消选中来选择一个。在我看来它   会一方面污染ViewModel,也觉得有   另一方面,关于观点的某些“知识”。

您可以轻松地继承ObservableCollection<T>以可重用的方式创建此逻辑。然后在你的ViewModel中放入一些public SelectableCollection<T> MyItems {get;set;},其中选择/互斥等由SelectableCollection处理,依此类推。

结论:MVVM完全是关于功能的可重用性和封装。