MVVM简介

来源:互联网 发布:windows.old win10更新 编辑:程序博客网 时间:2024/05/21 22:38

MVVM,即Model-View-ViewModel。该设计模式的主要思路是:模型(Model)和视图(View)通过视图模型(View Model)进行交互,以此来剥离逻辑和界面之间的耦合。MVVM设计模式的应用目前就我所知只能建立在WPF技术之上,这是因为WPF提供了几种能够使MVVM成为可能的技术,比如数据绑定,下面将会提到。

使用该设计模式好处:

1. 提高代码的可复用性- 在产品升级换代的时候,我们的大部分逻辑代码仍将能继续使用,而不会因为用户界面的变化而需要修改逻辑的代码。

2. 提高代码可测试性 - 由于逻辑和界面不再有耦合,基本上可以为所有的代码写测试用例,大大提高代码质量。

3. 不再需要Code-Behind代码 - 通过WPF的特定技术,可以不再需要写Code-Behind代码,比如按钮的Click操作,以前的技术,我们需要在Code-Behind注册Click事件的处理函数,而WPF的绑定技术可以避免Code-Behind。

 

经过一段时间的学习和实践,下面对MVVM模式进行简单的总结,下面的代码使用C#语言实现。

-- 如果你不懂WPF,在阅读下面内容之前,建议你先了解WPF的概念

 

Model

即模型,可以理解为数据模型和商业逻辑,它完全不依赖于视图。

 

View

即视图或者界面。

 

ViewModel

即视图模型或者界面模型,View会直接访问ViewModel,这种访问可以使用WPF的数据绑定技术来达到。需要特别注意的是ViewModel不会也不应该去访问View,比如在ViewModel中获取一个按钮实例。有些时候我们需要控制View的状态,这种情况可以在ViewModel中设计合适的状态类型,然后和View中特定的控件进行绑定。

我们可以实现一个ViewModel 的抽象类来作为所有ViewModel的基类,代码如下:

public abstract class ViewModel : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void OnPropertyChanged(string propertyName)

    {

        if(PropertyChanged != null)

        {

              PropertyChagned(this, new PropertyChangedEventArgs(propertyName))

        }

    }

}

如果你不知道接口INotifyPropertyChanged用来干什么的,那就在网上搜索一下吧!

 

Model 和 ViewModel 之间的关系

一般情况下ViewModel会包含一个Model实例,然后通过自己的接口把Model的数据暴露出来让View来使用。 

public class Customer

{

     public string Name {get; set;}

}

 

public class CustomerViewModel : ViewModel

{

    public CustomerViewModel(Customer customer)

    {

         m_Customer = customer;

    }

 

    private Customer m_Customer;

    public string Name

    {

        get { return m_Customer.Name; }

        set

        {

            if(m_Customer.Name ! = value)

            {

                 m_Customer.Name = value;

                 OnPropertyChanged("Name");

             }

        }

    }

}

 

问题:如果Model中有一个List,并且需要显示到View中,那么ViewModel应该怎么处理呢?比如:

public class Customer

{

    public List<string> Habites { get; private set;} 

}

 

最直接的方法就是同样建立一个对应的ObservableCollection<string>。但是你会发现一个问题:怎么同步Model和ViewModel的这两个集合?最直接的方法就是通过事件来通知了,但是你会发现这样的代码并不是很简洁。目前我也没有一个好办法来解决这个问题:(。

 

ViewModel 和 View 之间的关系

ViewModel和View之间的关系是控制和显示的关系,ViewModel会控制View的显示,包括显示的内容和视图的状态。一般情况我们会为ViewModel定义一个DataTemplate,比如:

<DataTemplate DataType="{x:Type local:CustomerViewModel}">

    <Grid>

         <TextBlock Text="{Binding Name}"/>

    </Grid>

</DataTemplate>

 

按钮的Click事件的处理等,我们不再通过注册事件来处理,而是把ViewModel中的Command绑定到按钮中,比如

<Button Command={Binding AddCustomerCommand}/>

这样就避免了Code-Behind了,逻辑代码可以不依赖于界面。

 

常见问题及技术解决:

1. 事件绑定不了Command。

在实际的应用当中,你会发现有些时候很难做到不使用Code-Behind,比如一些事件,例如MouseDoubleClick,这些并不能进行Command的绑定,但是事实上,WPF已经提供了另一种技术 -- Attached Property -- 来解决的。网上有各种各样的Attached Property实现,但你遇到困难时不妨搜索一下。

这是一篇关于Attached Property的简单文章:http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx

 

 

2. Dialog怎么应用MVVM。

这也是比较常见的问题,网上也有不少讨论,我将会总结一下我是怎么处理这个问题的。

 

View 和 Model 之间的关系

你会发现我们其实可以直接给Model定义View,而且免去了ViewModel这层,这显得更简单。但是这样做我个人觉得并不合适,这样做有可能会使你的Model变的不是很纯粹,比如:最后你可能会定义一些控件界面状态的字段来控制界面的状态,别忘了我们的目的就是为了让Model和View不再有任何耦合,除非你的觉得你的Model非常的简单,不会有任何的影响,不然最后又会回到原来的很糟糕的状态--逻辑和视图绑定到一块了。

 

下面是我学习的一片文章,里面还有一个很好的例子。

参考:

1. http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

 

原创粉丝点击