首先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. Droid4x设置代理抓包

    Droid4x也是基于virtualbox+x86架构的   代理设置 设置->WIFI->鼠标按住WiredSSID选项不放->修改网络->显示高级选项->代理-> ...

  2. 如何区分SNAT和DNAT

    从定义来讲它们一个是源地址转换,一个是目标地址转换.都是地址转换的功能,将私有地址转换为公网地址.要区分这两个功能可以简单的由连接发起者是谁来区分:       内部地址要访问公网上的服务时(如web ...

  3. openstack 常用命令

    转自: docs.openstack.org $ nova boot --image ubuntu-cloudimage --flavor 1 --user-data mydata.file

  4. pycharm 2016 注册码

    43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...

  5. C#之文本操作

    [转载]C#文件操作大全(SamWang) 文件与文件夹操作主要用到以下几个类: 1.File类: 提供用于创建.复制.删除.移动和打开文件的静态方法,并协助创建 FileStream 对象. msd ...

  6. linux日常小坑

    一.权限 1.文件权限 改动文件权限和所有权的命令有如下两个: chmod -更改权限 chown -更改所有权 不过,只有用户是当前所有者或者根用户,才能实际更改文件的权限或所有权,这一点大家要注意 ...

  7. [Linux]centOS7下RPM安装Perl

    1.下载rpm依赖包,依照顺序安装. perl-parent-0.225-244.el7.noarch   perl-HTTP-Tiny-0.033-3.el7.noarch   perl-podla ...

  8. 汉企PHP开班

    明天PHP正式开班,没什么大目标 ,在四个半月的时间吧基础知识掌握牢固,自信的面对企业.

  9. IOS - AFN

    #import "ViewController.h"#import "AFNetworking.h"#import "SSZipArchive.h&q ...

  10. [Android Pro] http请求中传输base64出现加号变空格的解决办法

    reference to : http://blog.csdn.net/jsjwbxzy/article/details/45970231 try { des = URLEncoder.encode( ...