您的位置:首页 > 其它

WPF中MVVM模式详解

2018-03-11 22:43 911 查看
以前理解的MVVM模式=View+ViewModel+Model。其中:

View没什么可说的,相当于xaml文件定义的UI;
ViewModel承担了一大堆职责:获取数据(通过一个抽象出来的Service层)、数据验证、View状态控制、View交互提供(通过Command、Action等);
Model就简单了,就是一个数据的POTO类。
应该注意到的是,可以这样实现,但不能认为这就是MVVM模式

---------------------------------------------------------------------------------------------------------------------------------

先来看看Prism5文档 Implementing the MVVM Pattern
一节中对于MVVM中各层职责的归纳:

View

View是一个可视化元素,例如一个window、page、user control或data template。View定义了它所包含的控件的样式和布局。
View通过DataContext属性来映射ViewModel,然后将其中的控件绑定到View Model暴露属性和命令上。
View可以自定义和View Model之间的数据绑定行为。例如:View可以用值转换器格式化将要显示到UI上的数据;View也可以用数据验证规则来为用户提供附加的输入验证功能。
View定义和处理UI显示行为,如View Model中状态改变或用户交互触发的动画或变换(Transformation)效果
当UI逻辑难以通过XAML定义,或者需要直接操作View中某个控件时,可以在View的后台代码中实现。

View Model
View Model是一个非可视化类,并且不继承任何WPF基类。它封装了程序与用户交互的呈现逻辑(Presentation Logic,个人理解就是在某个状态下或用户执行某个操作后界面应该先呈现什么、再呈现什么等等;至于呈现的是哪个控件、长什么样子,那是UI逻辑)。View Model可独立于View和Model进行测试。
View Model原则上不直接引用View。它主要定义用于View进行绑定的属性、命令(提供View要显示的内容和可执行的操作)。View Model通过INotifyPropertyChanged和INotifyCollectionChanged接口中的变化通知事件来通知View任何状态的变化。
View Model协调了View和Model之间的交互。它可以对数据进行转换或加工以使View更容易使用,也可以定义一些Model中没有的数据(来让View使用)。它也可以通过IDataErrorInfo或INotifyDataWErrorInfo接口来提供数据验证。
View Model可以定义一些逻辑状态并通过View来具现化给用户。

Model
Model类也是一个非可视化类,它封装了应用的数据和业务逻辑(Business Logic)。它主要负责管理应用数据,并通过封装业务规则和验证逻辑来确保数据的一致性和正确性。
Model类并不直接引用View Model和View,并且不依赖任何一个特定的View和View Model实现。
Model类常常提供一些属性,并通过INotifyPropertyChanged和INotifyCollectionChanged接口来提供属性变化通知事件。这让View实现数据绑定变得异常简单。表示一个集合的Model类通常会继承自ObservableCollection<T>类。
Model类通常利用IDataErrorInfo或INotifyDataErrorInfo接口来提供数据验证和错误信息报告。
Model类通常会与封装了数据访问和数据缓存的Service或Repository实例结合起来使用。

---------------------------------------------------------------------------------------------------------------------------------------

对于C/S、B/S架构的系统,我们一般会在界面层范围内(Client或前端)独立出一个接口层用来和Server层进行交互,叫Service层(或Repository层)。

我们也会有许多映射数据库数据结构的POTO类。

以前理解的MVVM模式把太多职责扔给了ViewModel,导致ViewModel过于臃肿,而Model又显得过于清闲:ViewModel几乎承担了Model的所有职责,而ViewModel和Model之间的交互被完全舍弃了。

真正的MVVM不应该是这样的。

我觉得真正的MVVM模式中Model层应该由Service层和POTO类共同组成,用来给ViewModel提供数据以及处理ViewModel对数据的修改请求。

举个例子,比如说我们要显示一个订单列表(Order List),订单列表中根据订单类型的不同,会以不同的DataTemplate显示,并且可以根据订单类型进行筛选。

按照MVVM进行设计,则每层的核心内容如下:

View层:OrderListView、各种Order的DataTemplate,及一个DataTemplateSelector。
View Model层:一个Model层的引用、各种View层的状态控制、各种View层的操作逻辑。
public class OrderListViewModel:INotifyPropertyChanged
{
private string _orderType;
public string OrderType
{
get{ return _orderType;}
set
{
_orderType=value;
OnPropertyChanged(nameof(OrderType));
}
}
private OrderListDataProvider _orderList;
public OrderListDataProvider OrderList
{
get { return _orderList;}
set
{
_orderList=value;
OnPropertyChanged(nameof(OrderList));
}
}
public OrderListViewModel(OrderListDataProvider provider)
{
this.OrderList=provider;
RequestData();//可以通过导航接口实现View激活后再请求数据
}

void RequestData()
{
if ( _orderList != null)
{
_orderList.RequestData(_orderType);
}
}

void OnPropertyChanged(string pName).....
}


Model层:Order类和各个Order子类、OrderService等的组合
public class OrderListDataProvider:ObservableCollection<Order>
{
private OrderService _service;
public OrderListDataProvider(OrderService service)
{
_service=service;
}

void RequestData(string orderTypes)
{
//用_service请求数据
//将获取的数据填充到Items中.
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  wpf mvvm