Model和ViewModel之间的通用MVVM数据交换

目录

介绍

代码

示例用法


介绍

我一直在开发一个工具来帮助团队中的其他开发人员为他们的MVC应用程序创建菜单项。所讨论的工具是一个使用MVVM模式的WPF桌面应用程序。我正在编写模型和相关的视图模型,这让我感到震惊,这些年来我一直在艰难地这样做。我在*每个ViewModel*中编写了一系列方法,在模型和视图模型之间来回切换数据。对于某些模型来说,这涉及20个或更多属性,并且支持它们所需的编码是纯粹的苦差事。昨天,我提出了另一种选择。

代码

我使用以下代码创建了一个类,并从我的视图模型类继承了该类:

public enum MVVMDirection { FROM, TO };

/// <summary>
/// ViewModel base class
/// </summary>
public class VMBase
{
    /// <summary>
    /// Move the data from the model to the viewmodel, using reflection. 
    /// Property names in both objects MUST be the same (both name and type)
    /// </summary>
    /// <typeparam name="TModel">The model's type</typeparam>
    /// <param name="model">The model object the data will be moved from</param>
    public void UpdateFromModel<TModel>(TModel model)
    {
        this.Update<TModel>(model, MVVMDirection.FROM);
    }

    /// <summary>
    /// Move the data from the viewmodel to the model, using reflection. 
    /// Property names in both objects MUST be the same (both name and type)
    /// </summary>
    /// <typeparam name="TModel">The model's type</typeparam>
    /// <param name="model">The model object the data will be moved from</param>
    public void UpdateToModel<TModel>(TModel model)
    {
        this.Update<TModel>(model, MVVMDirection.TO);
    }

    /// <summary>
    /// 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.
    /// </summary>
    /// <typeparam name="TModel">The model's type</typeparam>
    /// <param name="model">The model object the data will be moved to/from</param>
    /// <param name="direction">The direction in which the update will be performed</param>
    public void Update<TModel>(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<mymodel>(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<MyModel>(modelObj);

// change the viewmodel property values
// and then move it back to the model
vmObj.UpdateToModel<MyModel>(modelObj);

// save your model to the data source from which it was retrieved
modelObj.CallYourSaveMethod();

我不可能想出一个确定的用例列表,我真的对实现样式的宗教讨论不感兴趣,所以我希望你能够了解如何利用这些代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值