最近. NET 8 的 WPF 推出了 WPF File Dialog改进,这样无需再引用 Win32 命名空间就可以实现文件夹的选择与存储了,算是一个很方便的改进了。顺手写了一个小的 WPF 程序,在使用 Model-View-ViewModel(MVVM) 模式的时候,我不想使用 Prism 等重量级的框架,找了一个轻量级的 MVVM Community Toolkit (以下简称 MVVM Toolkit)。

在现代 WPF 应用程序开发中,遵循 MVVM(Model-View-ViewModel)模式已成为一种标准做法。MVVM 模式视图和逻辑分离,提高了代码的可测试性、可维护性。

MVVM Toolkit 核心功能

MVVM Toolkit 提供了一系列的功能,使得在 WPF 等程序中实现 MVVM 更加简单。

  1. ViewModel 基类:基类(例如 ObservableObject)为实现属性更改通知提供了基础结构,简化了 ViewModel 的创建过程。
  2. 命令的实现:MVVM Toolkit 提供了易于使用的命令实现(RelayCommand ),允许 View 以声明方式绑定到 ViewModel 上的方法。
  3. 弱消息机制:弱消息机制(WeakReferenceMessenger)允许不同对象之间收发消息,而不会造成内存泄漏。

安装

使用 nuget 安装到 WPF 项目中即可。由于 MVVM Toolkit 面向. NET Standard,所以可在任何应用平台上使用:UWP、WinForms、WPF、Xamarin、Uno 等。

Install-Package CommunityToolkit.Mvvm

代码生成

在 MVVM Toolkit 中,代码生成器扮演着重要的角色。通过利用代码生成器,它能够自动化诸如属性更改通知和命令实现等常见任务,减少样板代码,提高开发效率。

例如,开发者可以通过简单的属性标记,自动实现 INotifyPropertyChanged 接口:

partial class MyViewModel : ObservableObject
{
[ObservableProperty]
private string name; [ObservableProperty]
private bool isEnabled;
}

以上代码会通过 Roslyn 的代码生成器功能生成如下代码:

 partial class MyViewModel
{
public string Name
{
get => name;
set => SetProperty(ref name, value);
} public bool IsEnabled
{
get => isEnabled;
set => SetProperty(ref isEnabled, value);
}
}

在没有 MVVM Toolkit 的情况下,开发者需要手动实现 MVVM 的各个部分。例如,实现 INotifyPropertyChanged 接口通常涉及创建大量样板代码:

public class MyViewModel : INotifyPropertyChanged
{
private string myProperty; public string MyProperty
{
get => myProperty;
set
{
myProperty = value;
OnPropertyChanged(nameof(MyProperty));
}
} public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

相比之下,MVVM Toolkit 不仅减少了需要编写的代码量,也降低了出错的可能性,使得开发更加专注于业务逻辑本身。

使用 MVVM Toolkit 创建 ViewModel

依赖属性与命令

以下是使用 MVVM Toolkit 创建 ViewModel 的一个简单示例:

public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private string title = "Hello, MVVM Toolkit!"; [RelayCommand]
private void DealWithData()
{
// 数据处理逻辑
}
}

ObservablePropertyRelayCommand 属性标记自动处理了属性更改通知和命令实现的细节,开发者只需关注业务逻辑,并在 XAML 中绑定对应的属性/命令,组件会自动生成对应的依赖属性。

注意,请一定使用 camelCase 命名法(可以带前导_),代码生成器会生成符合 PascalCase 标准的属性/方法名称。

弱引用消息

再看 WeakReferenceMessenger 在不同 ViewModel 或组件间发送和接收消息:

1. 定义消息类型

首先定义一个消息类型。消息可以是任何类或结构,通常包含发送者想要传递的数据:

public class MyMessage
{
public string Text { get; } public MyMessage(string text)
{
Text = text;
}
}

2. 发送消息

在一个 ViewModel 或组件中,你可以发送消息。假设有一个 SenderViewModel

public class SenderViewModel
{
private void SendMessage()
{
var message = new MyMessage("Hello from SenderViewModel");
WeakReferenceMessenger.Default.Send(message);
}
}

SendMessage 方法创建了一个 MyMessage 实例,并通过 WeakReferenceMessenger.Default.Send 方法发送。

3. 接收消息

在另一个 ViewModel 或组件中,你可以注册以接收特定类型的消息。例如,你可能有一个 ReceiverViewModel

public class ReceiverViewModel
{
public ReceiverViewModel()
{
// 注册以接收 MyMessage 类型的消息
WeakReferenceMessenger.Default.Register<MyMessage>(this, (recipient, message) =>
{
// 处理接收到的消息
string receivedText = message.Text;
// Do something with receivedText
});
}
}

ReceiverViewModel 的构造函数中,使用 WeakReferenceMessenger.Default.Register 方法注册了消息接收器,当发送方发送 MyMessage 类型的消息时,这个接收器将被调用。

4. 解除消息注册

在不再需要接收消息时,或者在对象被销毁之前,应该解除消息的注册,以避免内存泄漏:

public class ReceiverViewModel
{
public ReceiverViewModel()
{
WeakReferenceMessenger.Default.Register<MyMessage>(this, OnMessageReceived);
} private void OnMessageReceived(object recipient, MyMessage message)
{
// 处理消息
} ~ReceiverViewModel()
{
WeakReferenceMessenger.Default.Unregister<MyMessage>(this);
}
}

ReceiverViewModel 通过其析构函数取消注册(也可以使用 IDispose 实现),确保当 ViewModel 被回收时,不会有消息处理器的引用残留。

总结

MVVM Toolkit 为 WPF 开发者提供了一个强大且易用的工具,它极大地简化了 MVVM 模式实现过程,虽然其他框架(MVVM Light/Prism 等)也提供了类似功能,但它非常轻量,使用简单,非常适合小型工程使用。

本文使用 AI 帮助润色了部分内容,文章经过人工校对。

使用MVVM Toolkit简化WPF开发的更多相关文章

  1. 简化MVVM属性设置和修改 - .NET CORE(C#) WPF开发

    微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. 简化MVVM属性设置和修改 - .NET CORE(C#) WPF开发 阅读导航 常用类属性设 ...

  2. Mvvm Light Toolkit for WPF/Silverlight系列之搭建mvvmlight开发框架

    Mvvm Light Toolkit for WPF/Silverlight系列之搭建mvvmlight开发框架   本章节,我将通过示例介绍如何搭建mvvmlight开发环境.示例中的我会针对wpf ...

  3. MvvmLight学习篇—— Mvvm Light Toolkit for wpf/silverlight系列(导航)

    系列一:看的迷迷糊糊的 一.Mvvm Light Toolkit for wpf/silverlight系列之准备工作 二.Mvvm Light Toolkit for wpf/silverlight ...

  4. 【WPF开发备忘】使用MVVM模式开发中列表控件内的按钮事件无法触发解决方法

    实际使用MVVM进行WPF开发的时候,可能会用到列表控件中每行一个编辑或删除按钮,这时直接去绑定,发现无法响应: <DataGridTemplateColumn Header="操作& ...

  5. [WPF] 使用 MVVM Toolkit 构建 MVVM 程序

    1. 什么是 MVVM Toolkit 模型-视图-视图模型 (MVVM) 是用于解耦 UI 代码和非 UI 代码的 UI 体系结构设计模式. 借助 MVVM,可以在 XAML 中以声明方式定义 UI ...

  6. 使用MVVM设计模式构建WPF应用程序

    使用MVVM设计模式构建WPF应用程序 本文是翻译大牛Josh Smith的文章,WPF Apps With The Model-View-ViewModel Design Pattern,译者水平有 ...

  7. Prism+MaterialDesign+EntityFramework Core+Postgresql WPF开发总结 之 基础篇

    本着每天记录一点成长一点的原则,打算将目前完成的一个WPF项目相关的技术分享出来,供团队学习与总结. 总共分三个部分: 基础篇主要争对C#初学者,巩固C#常用知识点: 中级篇主要争对WPF布局与美化, ...

  8. 使用 MVVM Toolkit Source Generators

    关于 MVVM Toolkit 最近 .NET Community Toolkit 发布了 8.0.0 preview1,它包含了从 Windows Community Toolkit 迁移过来的以下 ...

  9. 领域驱动和MVVM应用于UWP开发的一些思考

    领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...

  10. MVVM框架从WPF移植到UWP遇到的问题和解决方法

    MVVM框架从WPF移植到UWP遇到的问题和解决方法 0x00 起因 这几天开始学习UWP了,之前有WPF经验,所以总体感觉还可以,看了一些基础概念和主题,写了几个测试程序,突然想起来了前一段时间在W ...

随机推荐

  1. shell: xcall

    #!/bin/bash ips=( 1.1.1.2 1.1.1.1 ) port= user= passwd= for i in ${ips[@]} do echo "== $i ==&qu ...

  2. Linux 修改文本dos/unix 格式

    使用 vi 命令打开文件,使用 :set ff 查看格式 如果显示dos,可使用 :set ff=unix 修改 pem 证书,使用 cat xx.key xx.crt DigiCertCA.crt ...

  3. 【算法】单调栈 & 单调队列学习笔记

    1. 单调栈简介 1.1 前言 今天是 2023/1/15,一中寒假集训阶段性的结束了.集训的学习笔记可以在本人 blogs 的[算法]标签栏中找. 马上就要过年了,提前祝大家新年快乐! 1.2 什么 ...

  4. VScode 中golang 调试 F5,json文件内容更改 Go

    调试:在Vscode软件中调试.go文件代码 1.1.1 确保调试文件正常运行 准备好.go文件,并且该文件能正常运行,终端输入命令运行程序,如:go run time.go 测试代码: packag ...

  5. 在Python中使用LooseVersion进行软件版本号比对

    技术背景 Python是一门极其热门.极其灵活的开发语言,其更新迭代的速度也非常的快速.有时候我们遇到不同的软件版本不同方法处理的情况,此时就需要用到版本号比对的工具.举一个例子说,我们要在pytho ...

  6. WPF中非递归(无后台代码)动态实现TreeView

    在UI界面中,树形视图是比较常用的表示层级结构的方式,WPF中提供了TreeView控件.对于TreeView控件的基本使用已经有很多文章.大都是介绍如何在XAML中使用硬编码的固定信息填充Treev ...

  7. CF1787E The Harmonization of XOR 题解

    CF1787E The Harmonization of XOR 题目大意 给定 \(n\) 个数 \([1, 2, 3, \cdots, n]\) 和两个正整数 \(k\) 和 \(x\). 将这些 ...

  8. DevOps |研发效能之环境、程序、配置、SQL变更管理

    本文主要是讲如何建立有效的环境.程序.配置.SQL变更和管理平台. ​几天前和一个朋友聊到环境.程序的配置变更,SQL变更和整个上线流程.之前我们在这块也做了很多,有做的好的也有做的一般的,借机都总结 ...

  9. 解决Eclipse中启动Tomcat报unable to start within 45 seconds问题

    启动项目的时候报Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds. If the server ...

  10. jenkins部署及gitlab联调

    jenkins部署及gitlab联调 目录 jenkins部署及gitlab联调 一.jenkins安装 1.环境优化 2.安装jdk java 环境 3.下载jenkins 4.启动Jenkins服 ...