目录
介绍
代码
示例用法
我一直在开发一个工具来帮助团队中的其他开发人员为他们的MVC应用程序创建菜单项。所讨论的工具是一个使用MVVM模式的WPF桌面应用程序。我正在编写模型和相关的视图模型,这让我感到震惊,这些年来我一直在“艰难地”这样做。我在*每个ViewModel*中编写了一系列方法,在模型和视图模型之间来回切换数据。对于某些模型来说,这涉及20个或更多属性,并且支持它们所需的编码是纯粹的苦差事。昨天,我提出了另一种选择。
我使用以下代码创建了一个类,并从我的视图模型类继承了该类:
public enum MVVMDirection { FROM, TO };
///
/// ViewModel base class
///
public class VMBase
{
///
/// Move the data from the model to the viewmodel, using reflection.
/// Property names in both objects MUST be the same (both name and type)
///
/// The model's type
/// The model object the data will be moved from
public void UpdateFromModel(TModel model)
{
this.Update(model, MVVMDirection.FROM);
}
///
/// Move the data from the viewmodel to the model, using reflection.
/// Property names in both objects MUST be the same (both name and type)
///
/// The model's type
/// The model object the data will be moved from
public void UpdateToModel(TModel model)
{
this.Update(model, MVVMDirection.TO);
}
///
/// Update to or from the model based on the specified direction. Property names in both
/// objects MUST be the same (both name and type), but properties used just for the view
/// model aren't affected/used.
///
/// The model's type
/// The model object the data will be moved to/from
/// The direction in which the update will be performed
public void Update(TModel model, MVVMDirection direction)
{
PropertyInfo[] mProperties = model.GetType().GetProperties();
PropertyInfo[] vmProperties = this.GetType().GetProperties();
foreach(PropertyInfo mProperty in mProperties)
{
PropertyInfo vmProperty = this.GetType().GetProperty(mProperty.Name);
if (vmProperty != null)
{
if (vmProperty.PropertyType.Equals(mProperty.PropertyType))
{
if (direction == MVVMDirection.FROM)
{
vmProperty.SetValue(this, mProperty.GetValue(model));
}
else
{
vmProperty.SetValue(model, mProperty.GetValue(this));
}
}
}
}
}
}
与任何代码一样,使用这些方法的方法不止一种。在我自己的例子中,我的典型ViewModel对象包含一个表示模型的属性,构造函数接受一个模型对象参数。从参数设置Model属性后,构造函数会对UpdateFromModel()方法执行初始调用。我的视图模型看起来像这样:
// ViewModelBase contains the methods that are discussed in this tip,
// and in my case, ViewModelBase inherits from
// a class called Notifiable which inherits from INotifyPropertyChanged
// and contains properties to support using view
// models in a WPF environment.
public partial class MyViewModel : ViewModelBase
{
private string property1;
public MyModel Model { get; set; }
public string Property1
{
get { return this.property1; }
set
{
if (this.property1 != value)
{
this.property1 = value;
// in the "Notifiable" class
this.NotifyPropertyChanged();
}
}
}
public MyViewModel(MyModel model)
{
this.Model = model;
// in the ViewModelBase class
this.UpdateFromModel(this.Model);
}
}
我使用Model属性是因为我不希望在用户准备好之前提交对模型数据的更改(由UI中的操作决定)。当然,您可以直接从viewmodel属性更新模型的值(通过应用程序UI操作),如果这是您需要做的,但这不是*我*做的方式。至于对象属性之间的数据传输,您可以想象一下这类代码的长列表,您可以理解为什么我想出了这些基类方法。
我知道你们中的一些人阅读这个可能会有不同的观点,因为它与你放置代码的位置以及你如何实现MVVM模式有关,所以这里有一个例子,它有一点点不同,在实例化视图模型后,你也可以在viewmodel对象的外部执行初始方法调用,如下所示:
// create and populate your model however you want/need to do it
MyModel modelObj = new MyModel();
// do something to populate your model if necessary (my model objects are
// created and populated via calls to the database)
// create your viewmodel
VMMyModel vmObj = new VMMyModel();
// and move the model data to the viewmodel
vmObj.UpdateFromModel(modelObj);
// change the viewmodel property values
// and then move it back to the model
vmObj.UpdateToModel(modelObj);
// save your model to the data source from which it was retrieved
modelObj.CallYourSaveMethod();
我不可能想出一个确定的用例列表,我真的对实现样式的宗教讨论不感兴趣,所以我希望你能够了解如何利用这些代码。