WPF MVVM模式简介
WPF是Windows Presentation Foundation的缩写,它是一种用于创建桌面应用程序的用户界面框架。WPF支持多种开发模式,其中一种叫做MVVM(Model-View-ViewModel)。
什么是MVVM?
MVVM是一种软件架构模式,它将应用程序分为三个层次:Model(模型),View(视图)和ViewModel(视图模型)。Model表示应用程序的数据和业务逻辑,View表示应用程序的用户界面,ViewModel表示View和Model之间的桥梁,它负责处理View的数据绑定和用户交互。
为什么要使用MVVM?
使用MVVM有以下几个好处:
- 降低了View和Model之间的耦合度,使得它们可以独立地开发和测试。
- 提高了代码的可重用性和可维护性,因为ViewModel可以在不同的View之间共享。
- 简化了单元测试,因为ViewModel不依赖于具体的UI控件。
- 支持双向数据绑定,使得View可以自动更新Model的变化,反之亦然。
- 利用了WPF提供的强大特性,如命令、依赖属性、数据注解等。
下图我们可以直观的理解MVVM谁急模式:

View: 使用XAML呈现给用户的界面,负责与用户交互,接收用户输入,把数据展现给用户。
Model: 事物的抽象,开发过程中涉及到的事物都可以抽象为Model,例如姓名、年龄、性别、地址等属性.不包含方法,也不需要实现INotifyPropertyChanged接口.
ViewModel: 负责收集需要绑定的数据和命令,聚合Model对象,通过View类的DataContext属性绑定到View。同时也可以处理一些UI逻辑。
如何实现MVVM?
实现MVVM需要遵循以下几个步骤:
- 创建一个Model类,定义应用程序所需的数据和业务逻辑。
- 创建一个ViewModel类,继承自INotifyPropertyChanged接口,并实现属性变更通知。在ViewModel中定义与Model相关联的属性,并提供相应的命令来执行用户操作。
- 创建一个View类(通常是一个XAML文件),定义应用程序的用户界面。在View中使用数据绑定来连接ViewModel中的属性和命令,并设置相关的样式和行为。
- 在App.xaml或其他合适的地方创建一个ViewModel实例,并将其作为View中DataContext属性值。
- 示例代码:
// Model class
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
// ViewModel class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows;
namespace WpfApp1
{
public class UserInfoViewModel : INotifyPropertyChanged
{
private User user;
public UserInfoViewModel()
{
user = new User();
SaveCommand = new RelayCommand(Save);
CancelCommand = new RelayCommand(Cancel);
}
public string UserName
{
get { return user.Name; }
set
{
user.Name = value;
OnPropertyChanged("UserName");
}
}
public int UserAge
{
get { return user.Age; }
set
{
user.Age = value;
OnPropertyChanged("UserAge");
}
}
public string UserInfo
{
get { return $"Name:{UserName} Age:{UserAge}"; }
}
public ICommand SaveCommand { get; private set; }
public ICommand CancelCommand { get; private set; }
private void Save(object parameter)
{
// Save user data to database or service
MessageBox.Show("User data saved!");
OnPropertyChanged("UserInfo");
}
private void Cancel(object parameter)
{
// Close dialog window without saving data
var window = parameter as Window;
if (window != null)
window.Close();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
//Command class
public class RelayCommand : ICommand
{
public RelayCommand(Action<object> action)
{
DoExecute = action;
}
public event EventHandler? CanExecuteChanged;
public Func<object, bool>? CanExecution { set; get; }
public Action<object>? DoExecute { set; get; }
public bool CanExecute(object? parameter)
{
if (CanExecution != null)
{
CanExecute(parameter);
}
return true;
}
public void Execute(object? parameter)
{
DoExecute!.Invoke(parameter!);
}
}
// View class (XAML file)
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="220" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Labels and textboxes for user name and age -->
<Label Content="Name:" Grid.Row="0" Grid.Column="0" Margin="10"/>
<TextBox Text="{Binding UserName}" Grid.Row="0" Grid.Column="1" Margin="10"/>
<Label Content="Age:" Grid.Row="1" Grid.Column="0" Margin="10"/>
<TextBox Text="{Binding UserAge}" Grid.Row="1" Grid.Column="1" Margin="10"/>
<Label Content="{Binding UserInfo}" Grid.Row="2" Grid.Column="1" Margin="10"/>
<!-- Buttons for save and cancel commands -->
<StackPanel Orientation= "Horizontal" HorizontalAlignment= "Right"
Grid.Row= "3" Grid.ColumnSpan= "2">
<Button Content= "Save" Command="{Binding SaveCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" Margin= "10"/>
<Button Content= "Cancel" Command="{Binding CancelCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}" Margin= "10"/>
</StackPanel>
</Grid>
</Window>
// View code-behind file
using System.Windows;
namespace WpfApp1
{
/// Interaction logic for UserInfoView.xaml
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Set the ViewModel as the DataContext of the View
this.DataContext = new UserInfoViewModel();
}
}
}
运行结果如下:

代码位置:
https://github.com/DXG88/WpfApp1.git
有哪些MVVM框架?
虽然可以手动实现MVVM模式,但是也有许多第三方库提供了更方便和高效地使用MVVM模式。以下是一些常见且流行的MVVM框架:
- Prism: 一个由微软支持的MVVM框架,提供了一系列服务和特性,如导航、模块化、事件聚合、命令、依赖注入等。
- MVVM Light: 一个轻量级的MVVM框架,提供了一些基础类和组件,如ViewModelBase, RelayCommand, Messenger等。
- Caliburn.Micro: 一个基于约定而非配置的MVVM框架,提供了一些高级特性,如屏幕激活/关闭生命周期管理、自动绑定、窗口管理器等。
作者:百宝门-董校刚
原文地址:https://blog.baibaomen.com/wpf-mvvm模式简介/
WPF MVVM模式简介的更多相关文章
- MVVM模式和在WPF中的实现(一)MVVM模式简介
MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...
- WPF MVVM从入门到精通1:MVVM模式简介
原文:WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 W ...
- WPF MVVM模式的一些理解
/*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...
- WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍
WPF自学入门(十一)WPF MVVM模式Command命令 在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...
- wpf mvvm模式下CommandParameter传递多参
原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...
- WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...
- WPF MVVM模式下的无阻塞刷新探讨
很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...
- WPF自学入门(十一)WPF MVVM模式Command命令
在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...
- WPF MVVM模式下ComboBox级联效果 选择第一项
MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...
- WPF MVVM模式
1. MVVM MVVM的设计模式最早于2005年由微软的WPF和Silverlight架构师John Gossman在他的博客中提到. WPF中采用MVVM的架构可以获得以下好处: 1. 将UI和业 ...
随机推荐
- long数据类型跨平台问题
源代码 #include <iostream> int main() { std::cout << "size of long : " << s ...
- Vue插槽与作用域插槽
title: Vue插槽与作用域插槽 date: 2024/6/1 下午9:07:52 updated: 2024/6/1 下午9:07:52 categories: 前端开发 tags: VueSl ...
- 利用nodejs的require.context来实现不用写impor导入组件
先给你们看下目录结构 stuendt和teacharts还有util是同级 主要是componentRegister.js文件 function changStr(str) { return str. ...
- xv6 内存管理
前文讲述了 xv6 的启动过程,本文接着讲述 xv6 内存管理的部分,直接来看. 公众号:Rand_cs 启动部分完善 前文只是介绍了启动的过程,但是各类函数之间的调用,地址的变换,内存布局的变化并没 ...
- C#.NET 使用Windows证书库中的证书
public static X509Certificate2 GetCertificate(string commonName, StoreName storeName) { X509Certific ...
- 玩爆你的手机联系人--T9搜索
自己研究了好几天联系人的T9搜索算法, 先分享出来给大家看看. 欢迎指教.如果有大神有更好的T9搜索算法, 那更好啊,大家一起研究研究,谢谢. 第一部分是比较简单的获取手机联系人. 获取联系人 ...
- vue bus传参
新建一个js文件,命名为bus.js.bus.js文件的内容为: import Vue from 'vue' const bus = new Vue() export default bus 页面de ...
- Java代码忽略https证书:解决No subject alternative names present问题 HttpURLConnection https请求
Java代码忽略https证书:解决No subject alternative names present问题 import org.slf4j.Logger; import org.slf4j.L ...
- Linux chmod -bash: ./xx.sh: Permission denied的解决方案
Linux -bash: ./xx.sh: Permission denied的解决方案启动tomcat命令:./startup.sh之后提示-bash: ./startup.sh: Permissi ...
- vc++6.0设置字体
vc++6.0设置字体 如上图, 在注册表上找到这个位置. 自已设置FontFace和FontSize即可. 计算机\HKEY_CURRENT_USER\Software\Microsoft\Devs ...