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需要遵循以下几个步骤:

  1. 创建一个Model类,定义应用程序所需的数据和业务逻辑。
  2. 创建一个ViewModel类,继承自INotifyPropertyChanged接口,并实现属性变更通知。在ViewModel中定义与Model相关联的属性,并提供相应的命令来执行用户操作。
  3. 创建一个View类(通常是一个XAML文件),定义应用程序的用户界面。在View中使用数据绑定来连接ViewModel中的属性和命令,并设置相关的样式和行为。
  4. 在App.xaml或其他合适的地方创建一个ViewModel实例,并将其作为View中DataContext属性值。
  5. 示例代码:
// 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模式简介的更多相关文章

  1. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  2. WPF MVVM从入门到精通1:MVVM模式简介

    原文:WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 W ...

  3. WPF MVVM模式的一些理解

    /*本文转自 http://www.cnblogs.com/sirkevin/archive/2012/11/28/2793471.html */ 使用WPF+Mvvm开发一年多,期间由于对Mvvm模 ...

  4. WPF自学入门(十一)WPF MVVM模式Command命令 WPF自学入门(十)WPF MVVM简单介绍

    WPF自学入门(十一)WPF MVVM模式Command命令   在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式 ...

  5. wpf mvvm模式下CommandParameter传递多参

    原文:wpf mvvm模式下CommandParameter传递多参 CommandParameter一般只允许设置一次,所以如果要传递多参数,就要稍微处理一下.我暂时还没找到更好的方案,下面介绍的这 ...

  6. WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制

    原文:WPF MVVM模式中,通过命令实现窗体拖动.跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护.但是,很多初学者会在使用MVVM的过程中遇到 ...

  7. WPF MVVM模式下的无阻塞刷新探讨

    很多时候我们需要做一个工作,在一个方法体里面,读取大数据绑定到UI界面,由于长时间的读取,读取独占了线程域,导致界面一直处于假死状态.例如,当应用程序开始读取Web资源时,读取的时效是由网络链路的速度 ...

  8. WPF自学入门(十一)WPF MVVM模式Command命令

    在WPF自学入门(十)WPF MVVM简单介绍中的示例似乎运行起来没有什么问题,也可以进行更新.但是这并不是我们使用MVVM的正确方式.正如上一篇文章中在开始说的,MVVM的目的是为了最大限度地降低了 ...

  9. WPF MVVM模式下ComboBox级联效果 选择第一项

    MVVM模式下做的省市区的级联效果.通过改变ComboBox执行命令改变市,区. 解决主要问题就是默认选中第一项 1.首先要定义一个属性,继承自INotifyPropertyChanged接口.我这里 ...

  10. WPF MVVM模式

    1. MVVM MVVM的设计模式最早于2005年由微软的WPF和Silverlight架构师John Gossman在他的博客中提到. WPF中采用MVVM的架构可以获得以下好处: 1. 将UI和业 ...

随机推荐

  1. OOP课第一阶段总结

    前三次OOP作业总结Blog 前言 作为第一次3+1的总结,这次题目集的难度逐渐升高,题量.阅读量和测试点的数量变化都很大,所以对我们的编程和理解能力提出了更高的要求.要求我们能够熟练的掌握正则表达式 ...

  2. numpy cumsum()函数简介

    函数原型:numpy.cumsum(a, axis=None, dtype=None, out=None) 可参考链接:https://docs.scipy.org/doc/numpy-1.10.1/ ...

  3. [Qt开发]当我们在开发兼容高分辨率和高缩放比、高DPI屏幕的软件时,我们在谈论什么。

    前言 最近在开发有关高分辨率屏幕的软件,还是做了不少尝试的,当然我们也去网上查了不少资料,但是网上的资料也很零碎,说不明白,这样的话我就做个简单的总结,希望看到这的你可以一次解决你有关不同分辨率下的所 ...

  4. redis 远程连接

    redis-cli -h host -p port -a password -h 服务器地址 -p 端口号 -a 密码

  5. vue动态页签

    效果图 前端 1 <template> 2 <!-- 总体情况 - 总览echarts --> 3 4 <div v-loading="loading" ...

  6. Docker入门系列之三:十二个Dockerfile指令

    本篇文章是关于Dockerfiles的,这是Docker系列文章的第三部分.如果您还没有读过第一部分,请先阅读它,您可以从全新的角度了解Docker容器概念. 第二部分是Docker生态系统的简要介绍 ...

  7. Css var 简述

    Css var 语法 var(custom-property-name, value) - custom-property-name 必须 变量必须以 --开头 后面可以是英文.数字连接符,区分大小写 ...

  8. PHP 程序员转 Go 语言的经历分享

    大家好,我是码农先森. 之前有朋友让我分享从 PHP 转 Go 的经历,这次它来了.我主要从模仿.进阶.应用这三个方面来描述转 Go 的经历及心得.模仿是良好的开端,进阶是艰难的成长,应用是认知的提升 ...

  9. Dell服务器配置RIAD并创建热备盘

    在系统启动期间,按F2键进入System Setup(系统设置)主菜单 单击Device Settings(设备设置). 单击所需的RAID controller(RAID控制器)设备. 4.单击Co ...

  10. Ubuntu 18.04安装xdrp以使用远程桌面

    背景 开发环境有一台服务器默认没有屏幕(被我拿走用来拓展屏幕了),有时候需要使用到界面但嫌弃拆显示器太麻烦,因此使用远程桌面来解决这个需求. 做法 安装xrdp sudo apt install -y ...