Wpf 用于集合的MVVM
我最近开始学习wpf,并尝试使用mvvm 我的理解是,在mvvm中,视图和模型都不应该知道另一个存在 我想做的是在屏幕上显示客户列表。但是如果我对viewModel编码如下所示。这类似于我在网上看到的许多例子,然后我得到了一些类似这样的代码Wpf 用于集合的MVVM,wpf,mvvm,Wpf,Mvvm,我最近开始学习wpf,并尝试使用mvvm 我的理解是,在mvvm中,视图和模型都不应该知道另一个存在 我想做的是在屏幕上显示客户列表。但是如果我对viewModel编码如下所示。这类似于我在网上看到的许多例子,然后我得到了一些类似这样的代码 class客户 { 公共字符串名称{get;set;} 公共字符串地址{get;set;} } 类MainWindowViewModel { ObservableCollection客户=新ObservableCollection(); 公共可观测收
class客户
{
公共字符串名称{get;set;}
公共字符串地址{get;set;}
}
类MainWindowViewModel
{
ObservableCollection客户=新ObservableCollection();
公共可观测收集客户
{
获取{返回客户;}
}
公共主窗口视图模型()
{
//cust1和cust2是客户对象
添加(cust1);
添加(cust2);
}
}
现在,如果我创建了我的MainWindowViewModel的一个实例,并将其设置为我的MainWindowView(我的视图)的datacontext,并且我进一步将viewmodelsCustomers属性绑定到一个列表框,那么视图将需要对包含我的模型的程序集的引用
所以我的问题是
1) 添加对MVVM中允许的模型程序集的引用,因为这意味着视图知道该模型
2) 更好的解决方案是将每个Customer对象包装在CustomerServiceWModel中,并让MainWindowViewModel包含CustomerServiceWModel的可见集合
而不是可观察到的客户收集。这将使模型与视图完全分离。我们通常创建CustomServiceWModel。这是由我们的通用CollectionViewModelBase类强制实现的。这表明用户界面使用的每个部分都是专门创建来显示的,我们在模型中没有任何与UI相关的代码,这些代码通常是可序列化的POCO
用户
类型的年龄
,但用户
只有出生日期
属性。如果您不想更改模型,那么使用Age
属性创建UserViewModel
将是一个不错的选择李>
MVVM模式与任何其他MVx模式(MVC、MVP等)相似,因为它鼓励关注点分离(SoC),从而提高代码的可维护性/可测试性。除了通常的SoC之外,MVVM还提供以下功能:
Model <= View
Model <= ViewModel <= View
Model您肯定希望将模型包装在仅查看的对象中,如下所示:
/// <summary>
/// Business model object : Should be in your separate business model only library
/// </summary>
public class BusinessModelObject
{
public string Prop1 { get; set; }
public int Prop2 { get; set; }
}
/// <summary>
/// Base notifying object : Should be in your GUI library
/// </summary>
public abstract class NotifyingObject<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, e);
}
private static readonly PropertyChangedEventArgs ModelPropertyChanged = new PropertyChangedEventArgs("Model");
private T _model;
public T Model
{
get { return _model; }
set
{
_model = value;
NotifyPropertyChanged(ModelPropertyChanged);
}
}
}
/// <summary>
/// Model decorator : Should be in your GUI library
/// </summary>
public class BusinessModelObjectAdapter : NotifyingObject<BusinessModelObject>
{
public BusinessModelObjectAdapter(BusinessModelObject model)
{
this.Model = Model;
}
private static readonly PropertyChangedEventArgs Prop1PropertyChanged = new PropertyChangedEventArgs("Prop1");
private string _prop1;
public string Prop1
{
get { return Model.Prop1; }
set
{
Model.Prop1 = value;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
private static readonly PropertyChangedEventArgs Prop2PropertyChanged = new PropertyChangedEventArgs("Prop2");
private int _prop2;
public int Prop2
{
get { return Model.Prop2; }
set
{
Model.Prop2 = value;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
//and here you can add whatever property aimed a presenting your model without altering it at any time
}
//
///业务模型对象:应位于单独的仅限业务模型库中
///
公共类BusinessModelObject
{
公共字符串Prop1{get;set;}
公共int Prop2{get;set;}
}
///
///基本通知对象:应位于GUI库中
///
公共抽象类NotifyingObject:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
public void NotifyPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(handler!=null)handler(this,e);
}
私有静态只读PropertyChangedEventArgs ModelPropertyChanged=新PropertyChangedEventArgs(“模型”);
私有T_模型;
公共T模型
{
获取{return\u model;}
设置
{
_模型=价值;
NotifyPropertyChanged(ModelPropertyChanged);
}
}
}
///
///模型装饰器:应该在您的GUI库中
///
公共类BusinessModelObjectAdapter:NotifyingObject
{
公共BusinessModelObjectAdapter(BusinessModelObject模型)
{
这个模型=模型;
}
私有静态只读属性ChangedEventArgs Prop1PropertyChanged=新属性ChangedEventArgs(“Prop1”);
私有字符串_prop1;
公共字符串Prop1
{
获取{return Model.Prop1;}
设置
{
Model.Prop1=值;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
私有静态只读属性ChangedEventArgs Prop2PropertyChanged=新属性ChangedEventArgs(“Prop2”);
私人内部程序2;
公共int Prop2
{
获取{return Model.Prop2;}
设置
{
Model.Prop2=值;
NotifyPropertyChanged(Prop1PropertyChanged);
}
}
//在这里,您可以添加任何属性来演示您的模型,而无需在任何时候对其进行更改
}
回答您的问题:
引用模型的视图有什么不好?当它简化代码时,这是绝对正确的。另一种方法(模型->视图)是不好的做法
当您没有特殊需求时,不需要将每个客户对象包装在CustomerServiceWModel中。我建议遵循一种务实的方式,并保持代码简单
您可能对的BookLibrary示例应用程序感兴趣,该应用程序显示了您在此处描述的场景。当我通过代码隐藏将视图的DataContext设置为viewModel时