WPF MVVM示例讲解
在没给大家讲解wpf mwm示例之前先给大家简单说下mvvm理论知识:
wpf技术的主要特点是数据驱动ui,所以在使用wpf技术开发的过程中是以数据为核心的,wpf提供了数据绑定机制,当数据发生变化时,wpf会自动发出通知去更新ui。
我们使用模式,一般是想达到高内聚低耦合。在wpf开发中,经典的编程模式是mvvm,是为wpf量身定做的模式,该模式充分利用了wpf的数据绑定机制,最大限度地降低了xmal文件和cs文件的耦合度,也就是ui显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。与winform开发相比,我们一般在后置代码中会使用控件的名字来操作控件的属性来更新ui,而在wpf中通常是通过数据绑定来更新ui;在响应用户操作上,winform是通过控件的事件来处理,而wpf可以使用命令绑定的方式来处理,耦合度将降低。
首先mvvm设计模式的结构
views: 由window/page/usercontrol等构成,通过databinding与viewmodels建立关联;
viewmodels:由一组命令,可以绑定的属性,操作逻辑构成;因为view与viewmodel进行了解耦,我们可以对viewmodel进行unit test;
models:可以是实体对象或者web服务;
下面通过一个简单的例子,来介绍一些wpf mvvm模式。示例将展示一个图片浏览器,打开图片,放大/缩小图片大小。首先项目结构:
ui:
<grid> <dockpanel> <menu dockpanel.dock="top"> <menu> <menuitem header="_open" command="{binding openfilecommand}"/> </menu> <menu> <menuitem header="_zoomin" command="{binding zoomcommand}" commandparameter="zoomin"/> </menu> <menu> <menuitem header="_zoomout" command="{binding zoomcommand}" commandparameter="zoomout"/> </menu> <menu> <menuitem header="_normal" command="{binding zoomcommand}" commandparameter="normal"/> </menu> </menu> <scrollviewer> <image source="{binding imagepath}" stretch="none"> <image.layouttransform> <scaletransform scalex="{binding zoom}" scaley="{binding zoom}"/> </image.layouttransform> </image> </scrollviewer> </dockpanel> </grid>
viewmodelbase(用来实现修改通知):
public class viewmodelbase : inotifypropertychanged { public event propertychangedeventhandler propertychanged; protected virtual void onpropertychanged(string propname) { if(propertychanged!=null) { propertychanged(this, new propertychangedeventargs(propname)); } } }
openfilecommand:
public class openfilecommand : icommand { private mainviewmodel _data; public openfilecommand(mainviewmodel data) { _data = data; } public event eventhandler canexecutechanged; public bool canexecute(object parameter) { return true; } public void execute(object parameter) { openfiledialog dialog = new openfiledialog() { filter = "image files|*.jpg;*.png;*.bmp;*.gif" }; if(dialog.showdialog().getvalueordefault()) { _data.imagepath = dialog.filename; } }
zoomcommand:
public enum zoomtype { zoomin = 0, zoomout = 1, normal = 2 } public class zoomcommand : icommand { private mainviewmodel _data; public zoomcommand(mainviewmodel data) { _data = data; } public event eventhandler canexecutechanged { add { commandmanager.requerysuggested += value; } remove { commandmanager.requerysuggested -= value; } } public bool canexecute(object parameter) { return _data.imagepath != null; } public void execute(object parameter) { zoomtype type = (zoomtype)enum.parse(typeof(zoomtype), (string)parameter, true); switch(type) { case zoomtype.normal: _data.zoom = 1; break; case zoomtype.zoomin: _data.zoom *= 1.2; break; case zoomtype.zoomout: _data.zoom /= 1.2; break; } } }
mainviewmodel:
public class mainviewmodel : viewmodelbase { private string _imagepath; public string imagepath { get { return _imagepath; } set { if (_imagepath != value) { _imagepath = value; onpropertychanged("imagepath"); } } } private double _zoom = 1.0; public double zoom { get { return _zoom; } set { if(_zoom != value) { _zoom = value; onpropertychanged("zoom"); } } } private icommand _openfilecommand; public icommand openfilecommand { get { return _openfilecommand; } } private zoomcommand _zoomcommand; public zoomcommand zoomcommand { get { return _zoomcommand; } } public mainviewmodel() { _openfilecommand = new openfilecommand(this); _zoomcommand = new zoomcommand(this); } }
下一步我们要做的是将mainviewmodel绑定到mainwindow上,我们可以通过下面两种方式绑定:
1. 直接在mainwindow的code behind中进行绑定:
public mainwindow() { initializecomponent(); datacontext = new mainviewmodel(); }
2. 在app.xaml后台代码中绑定(将app.xaml中startupuri="mainwindow.xaml"删除掉):
public app() { mainwindow window = new mainwindow(); window.datacontext = new mainviewmodel(); window.show(); }
运行效果图如下:
以上就是针对wpf mvvm示例讲解的全部内容,并附有效果图,看着还不错吧,希望大家能够喜欢,欢迎提出宝贵意见。