WPF MVVM示例讲解
作者:mrr 发布时间:2022-04-16 22:47:20
在没给大家讲解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();
}
运行效果图如下:


猜你喜欢
- 本文实例讲述了Java实现的读取资源文件工具类ResourcesUtil。分享给大家供大家参考,具体如下:package com.gclou
- 建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现。为了方便,这里我们将
- 在Java的逻辑运算符中,有这么四类:&&(短路与),&,|,||(短路或)。&&和&都是表
- import java.io.*;/** * Created by tang on 14-3-1. */public c
- 前言上一篇文章已经介绍了fluent-mybatis项目的构建,文章地址:Java Fluent Mybatis实战之构建项目与代码生成篇上
- 我们在设计layout的时候,使用Split视图,就是左侧是代码,右侧是设计图,但是我们忽视了最上方的工具栏,这里才是真正的宝藏。下面教大家
- 1. 引入jar包pom.xml文件<?xml version="1.0" encoding="UTF-
- 一、前言Unity3D不仅仅可以开发游戏,还有非常多的开发方向,秉承着兴趣为先,将可以使用Unity制作的各种应用案例,分享如何进行开发,如
- SchedulingConfigurer实现动态定时,导致ApplicationRunner无效问题描述当通过SchedulingConfi
- 目录断言对象、数组、集合ObjectUtilsStringUtilsCollectionUtils文件、资源、IO 流FileCopyUti
- 什么是Spring BatchSpring Batch 是一个轻量级的、完善的批处理框架,旨在帮助企业建立健壮、高效的批处理应用。Sprin
- 本文实例讲述了Java实现的校验银行卡功能。分享给大家供大家参考,具体如下:步骤:首先区分借记卡和信用卡,然后就是校验卡号,最后根据银联Bi
- 一.简单介绍1.配置相关的依赖2.配置模式3写.mapper、controller、service4.配置yaml文件 配置mybatis全
- 项目开发中对于一些数据的处理需要用到多线程,比如文件的批量上传,数据库的分批写入,大文件的分段下载等。 通常会使用spring自带的线程池处
- 问题今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢?public vo
- 网上搜集了java的学习思维导图,分享给大家。01.Java程序设计(基础)02.Java程序设计(专题)03.客户端网页编程04.Java
- 1.顺
- 各个方法1. 得到class的成员变量首先得到object的class对象然后在class对象中用getDeclaredFields()方法
- JVM(Java虚拟机)是一个抽象的计算模型。就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域。目的是为构建在其上
- 在spring的注解 @RequestMapping 之下可以直接获取 HttpServletRequest 来获得诸如request he