WPF MVVM初体验
首先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初体验的更多相关文章
- 【全面解禁!真正的Expression Blend实战开发技巧】第七章 MVVM初体验-在DataGrid行末添加按钮
原文:[全面解禁!真正的Expression Blend实战开发技巧]第七章 MVVM初体验-在DataGrid行末添加按钮 博客更新较慢,先向各位读者说声抱歉.这一节讲解的依然是开发中经常遇到的一种 ...
- 查杀进程小工具——WPF和MVVM初体验
最近因为工作需要,研究了一下桌面应用程序.在winform.WPF.Electron等几种技术里,最终选择了WPF作为最后的选型.WPF最吸引我的地方,就是MVVM模式了.MVVM模式完全把界面和业务 ...
- 说不尽的MVVM(2) – MVVM初体验
知识预备 阅读本文,我假定你已经具备以下知识: C#.WPF基础知识 了解Lambda表达式和TPL 对事件驱动模型的了解 知道ICommand接口 发生了什么 某程序员接到一个需求,编写一个媒体渲染 ...
- MEF 插件式开发 - WPF 初体验
原文:MEF 插件式开发 - WPF 初体验 目录 MEF 在 WPF 中的简单应用 加载插件 获取元数据 依赖注入 总结 MEF 在 WPF 中的简单应用 MEF 的开发模式主要适用于插件化的业务场 ...
- "xaml+cs"桌面客户端跨平台初体验
"Xaml+C#"桌面客户端跨平台初体验 前言 随着 .Net 5的到来,微软在 .Net 跨平台路上又开始了一个更高的起点.回顾.Net Core近几年的成果,可谓是让.Ne ...
- Xamarin.iOS开发初体验
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0
- 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...
- 【Knockout.js 学习体验之旅】(1)ko初体验
前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...
- Knockout.js初体验
前不久在网上看到一个轻量级MVVM js类库叫Knockout.js,觉得很好奇,搜了一下Knockout.js相关资料,也初体验了一下,顿时感觉这个类库的设计很有意思.接下来就搞清楚什么是Knock ...
随机推荐
- 3. Android程序生成步骤
主要流程如下图所示: 所需要的工具列表 名称 功能介绍 在操作系统中的路径 aapt Android资源打包工具 ${ANDROID_SDK_HOME}/platform-tools/ ...
- 获取Spring容器Bean
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); ManageResolver mr = (Ma ...
- REACT 学习
1.React/React Native 的ES5 ES6写法对照表 http://bbs.reactnative.cn/topic/15/react-react-native-%E7%9A%84es ...
- (转)高性能网站架构之缓存篇—Redis集群增删节点
标签: 高性能架构集群缓存redis 上一篇文章,我们搭建了Redis-cluster集群,这篇博客跟大家讲一下如何在一个运行的集群上增加节点或者删除节点. Redis集群添加节点 首先我们要新建立一 ...
- ACM/ICPC 之 DFS求解欧拉通路路径(POJ2337)
判断是欧拉通路后,DFS简单剪枝求解字典序最小的欧拉通路路径 //Time:16Ms Memory:228K #include<iostream> #include<cstring& ...
- nyoj20_吝啬的国度_DFS
吝啬的国度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市, ...
- WP8图片缩放功能实现
最近在学习WP8,想实现WP微信中查看图片时的放大缩小功能. 网上找了两个解决方案: 1 利用GestureListener 这个类在Microsoft.Phone.Controls.Toolkit中 ...
- 【leetcode】Excel Sheet Column Title & Excel Sheet Column Number (easy)
Given a positive integer, return its corresponding column title as appear in an Excel sheet. For exa ...
- IOS - 开发之内存缓存机制
使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,是程序高效的运行.有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求. 内存缓存我们可以使用sdk中的NSURLC ...
- Xn数列(codevs 1281)
题目描述 Description 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn m, a, c, x0, n, g<=10^18 输入 ...