首先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 = ,
ZoomOut = ,
Normal =
} 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 = ;
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初体验的更多相关文章

  1. 【全面解禁!真正的Expression Blend实战开发技巧】第七章 MVVM初体验-在DataGrid行末添加按钮

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第七章 MVVM初体验-在DataGrid行末添加按钮 博客更新较慢,先向各位读者说声抱歉.这一节讲解的依然是开发中经常遇到的一种 ...

  2. 查杀进程小工具——WPF和MVVM初体验

    最近因为工作需要,研究了一下桌面应用程序.在winform.WPF.Electron等几种技术里,最终选择了WPF作为最后的选型.WPF最吸引我的地方,就是MVVM模式了.MVVM模式完全把界面和业务 ...

  3. 说不尽的MVVM(2) – MVVM初体验

    知识预备 阅读本文,我假定你已经具备以下知识: C#.WPF基础知识 了解Lambda表达式和TPL 对事件驱动模型的了解 知道ICommand接口 发生了什么 某程序员接到一个需求,编写一个媒体渲染 ...

  4. MEF 插件式开发 - WPF 初体验

    原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...

  5. "xaml+cs"桌面客户端跨平台初体验

    "Xaml+C#"桌面客户端跨平台初体验 前言   随着 .Net 5的到来,微软在 .Net 跨平台路上又开始了一个更高的起点.回顾.Net Core近几年的成果,可谓是让.Ne ...

  6. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  7. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  8. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

  9. Knockout.js初体验

    前不久在网上看到一个轻量级MVVM js类库叫Knockout.js,觉得很好奇,搜了一下Knockout.js相关资料,也初体验了一下,顿时感觉这个类库的设计很有意思.接下来就搞清楚什么是Knock ...

随机推荐

  1. PHP网页缓存技术

    http://blog.sina.com.cn/s/blog_646e51c40100weu9.html 前台静态化:把动态页面解析后保存为静态页面 文件缓存:把查询结果保存为文件,XML 内存缓存: ...

  2. git rebase简介(高级篇)

    原文:http://gitbook.liuhui998.com/4_3.html 一.基本   对于git rebase,你亦可以选择进行交互式的rebase.这种方法通常用于在向别处推送提交之前对它 ...

  3. 比较NHibernate和Entity Framework

    葡萄牙的一位开发者 Ricardo Peres 最近发布了一篇文章,以看起来无偏见的形式对领先的两种 .NET ORM:NHibernate 和 Entity Framework 进行了比较. 我们建 ...

  4. C#中 int.TryParse 的用法

    int i = -1;bool b = int.TryParse(null, out i);执行完毕后,b等于false,i等于0,而不是等于-1,切记. int i = -1;bool b = in ...

  5. Linq to 泛型集合查询集合包括大写M和年龄小于等于18

    #region Linq to 泛型集合查询集合包括大写M和年龄小于等于18            //List<Student> list = new List<Student&g ...

  6. jQuery获取循环中的选中单选按钮radio的值

    1.<input type="radio" name="testradio" value="jquery获取radio的值" /> ...

  7. centos7 安装mysql5.7.11注意事项

    centos7通过yum install mysql默认安装的是mariadb.至于为什么默认安装mariadb以及mariadb和mysql的区别,网上有很多说明.这里不再阐述,下面介绍下怎么另行下 ...

  8. 14. javacript高级程序设计-表单

    1. 表单脚本 1.1 基础知识 <from>元素表示表单: l acceptCharset:服务器能处理的字符集 l action:接受请求的URL l elements:表单中所有控件 ...

  9. ABAP 承运路单

    *&---------------------------------------------------------------------* *& Report  ZSDR010 ...

  10. 【Git】笔记4 分支管理1

    1.创建与合并分支 一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点: 每次提交,master分支都会向 ...