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. 使用 TiDB Vector 搭建 RAG 应用 - TiDB 文档问答小助手

    本文首发至TiDB社区专栏:https://tidb.net/blog/7a8862d5 前言 继上一次<TiDB Vector抢先体验之用TiDB实现以图搜图>后,就迫不及待的想做一些更 ...

  2. webpack配置图片处理

    # 安装 npm i -D url-loader html-loader file-loader # loader配置 module: { rules: [ // 图片处理 { test: /\.(p ...

  3. 国产大模型参加高考,同写2024年高考作文,及格分(通义千问、Kimi、智谱清言、Gemini Advanced、Claude-3-Sonnet、GPT-4o)

    大家好,我是章北海 今天高考,上午的语文结束,市面上又要来一场大模型参考的文章了. 我也凑凑热闹,让通义千问.Kimi.智谱清言一起来写一下高考作文. 公平起见,不加任何其他prompt,直接把题目甩 ...

  4. 一文搞懂 ARM 64 系列: 一文搞懂 ARM 64 系列: 函数调用传参与返回值

    函数调用涉及到传参与返回值,下面就来看下ARM 64中,参数与返回值的传递机制. 1 整数型参数传递 这里的整数型并不单指int类型,或者NSInteger类型,而是指任何能够使用整数表示的数据类型, ...

  5. Windows下cmd命令行sftp上传至Linux服务器

    1.Windows+R进入运行 2.输入cmd,进入命令行 3.命令建立连接 sftp 用户名@ip地址 例如: 输入密码,即可建立连接 上传方式: 1)直接拖动文件到命令行窗口,可以直接显示该文件的 ...

  6. C#字符串截取分割方法

    字符串操作:分割 Split.连接数组 Join.拼接 Format.截取 Substring.替换 Replace.左填充 PadLeft.右填充 PadRight.删除 Remove 1 //分割 ...

  7. Sass报错: Using / for division is deprecated

         原因是:当sass版本>= 1.33.0时,会不支持 / 这种语法:  解决方式一:      降低sass版本,将sass版本换成:"sass": "^ ...

  8. python之集合学习

    *******************集合{set}******************* 1.集合set 可变 特点:是由不同元素组成 是无序的 集合中元素必须是不可变类型例如(字符串/元祖/数字) ...

  9. 13-flex

    01 flex2个重要的概念 02 flex布局模型 03 flex相关属性 04 flex container相关属性 4.1 flex direction 不同的值会改变主轴的方向 4.2 fle ...

  10. 可重入锁思想,设计MQ迁移方案

    如果你的MQ消息要从Kafka切换到RocketMQ且不停机,怎么做?在让这个MQ消息调用第三方发奖接口,但无幂等字段又怎么处理?今天小傅哥就给大家分享一个关于MQ消息在这样的场景中的处理手段. 这是 ...