当前位置: 首页 > article >正文

C#/.NET 8实战:利用CommunityToolkit.Mvvm的Messenger打造一个简易实时协作白板

C#/.NET 8实战构建基于CommunityToolkit.Mvvm的实时协作白板系统在当今分布式协作日益普及的背景下实现多用户实时交互的白板工具成为许多应用场景的刚需。本文将带您从零开始利用.NET 8和WPF框架结合CommunityToolkit.Mvvm中的Messenger组件构建一个功能完整的实时协作白板系统。不同于简单的Demo我们将实现包含工具栏、画布、属性面板等多个视图协同工作的复杂应用展示MVVM模式下的高级消息通信机制。1. 项目架构设计与环境搭建1.1 创建.NET 8 WPF项目首先使用Visual Studio 2022创建一个新的WPF应用程序项目目标框架选择.NET 8.0。然后通过NuGet包管理器添加以下关键依赖Install-Package CommunityToolkit.Mvvm -Version 8.2.0 Install-Package System.Drawing.Common -Version 8.0.01.2 解决方案结构规划采用模块化设计思想我们将项目分为以下几个核心部分WhiteboardApp/ ├── Models/ # 数据模型 │ ├── Shape.cs # 图形基类 │ ├── Line.cs # 直线 │ ├── Rectangle.cs # 矩形 ├── ViewModels/ # 视图模型 │ ├── ShellViewModel.cs │ ├── ToolboxViewModel.cs │ ├── CanvasViewModel.cs │ ├── PropertiesViewModel.cs ├── Views/ # 用户界面 │ ├── MainWindow.xaml │ ├── ToolboxView.xaml │ ├── CanvasView.xaml │ ├── PropertiesView.xaml ├── Messages/ # 消息类型 │ ├── DrawingMessages.cs │ ├── ToolMessages.cs2. 核心消息系统设计2.1 定义消息类型在Messages/DrawingMessages.cs中定义白板应用所需的各种消息类型public abstract record DrawingMessage; public record BrushChangedMessage(Color NewColor) : DrawingMessage; public record ShapeAddedMessage(Shape NewShape) : DrawingMessage; public record SelectionChangedMessage(Shape? SelectedShape) : DrawingMessage; public record RequestCurrentBrushMessage : RequestMessageColor;2.2 实现消息收发基础创建一个静态的MessageHub类来统一管理消息收发public static class MessageHub { public static IMessenger Instance { get; } WeakReferenceMessenger.Default; public static void SendTMessage(TMessage message) where TMessage : class { Instance.Send(message); } public static void RegisterTMessage(object recipient, MessageHandlerobject, TMessage handler) where TMessage : class { Instance.Register(recipient, handler); } }3. 视图模型协同工作实现3.1 工具栏视图模型ToolboxViewModel负责管理绘图工具状态并通过消息通知其他组件public partial class ToolboxViewModel : ObservableObject, IRecipientRequestCurrentBrushMessage { [ObservableProperty] private Color _currentColor Colors.Black; public ToolboxViewModel() { MessageHub.Register(this); } partial void OnCurrentColorChanged(Color value) { MessageHub.Send(new BrushChangedMessage(value)); } public void Receive(RequestCurrentBrushMessage message) { message.Reply(CurrentColor); } }3.2 画布视图模型CanvasViewModel处理图形绘制和用户交互public class CanvasViewModel : ObservableObject, IRecipientBrushChangedMessage, IRecipientShapeAddedMessage { private Color _currentBrushColor; private readonly ObservableCollectionShape _shapes new(); public CanvasViewModel() { MessageHub.Register(this); var response MessageHub.Send(new RequestCurrentBrushMessage()); _currentBrushColor response.Response; } public void Receive(BrushChangedMessage message) { _currentBrushColor message.NewColor; } public void Receive(ShapeAddedMessage message) { _shapes.Add(message.NewShape); } public void AddLine(Point start, Point end) { var line new Line(start, end, _currentBrushColor); MessageHub.Send(new ShapeAddedMessage(line)); } }4. 高级消息模式应用4.1 使用Token实现消息频道为支持未来可能的多房间功能我们通过Token实现消息过滤// 在CanvasViewModel中注册特定频道的消息 WeakReferenceMessenger.Default.RegisterShapeAddedMessage, string( this, Room1, (r, m) { /* 只处理Room1的消息 */ }); // 发送特定频道的消息 WeakReferenceMessenger.Default.Send( new ShapeAddedMessage(newLine), Room1);4.2 属性变更通知优化利用NotifyPropertyChangedRecipients特性简化属性变更通知public partial class PropertiesViewModel : ObservableRecipient { [ObservableProperty] [NotifyPropertyChangedRecipients] private Shape? _selectedShape; public PropertiesViewModel() { MessageHub.RegisterSelectionChangedMessage(this); } public void Receive(SelectionChangedMessage message) { SelectedShape message.SelectedShape; } }5. 性能优化与调试技巧5.1 弱引用与内存管理CommunityToolkit.Mvvm的WeakReferenceMessenger已经内置了弱引用支持但开发者仍需注意及时注销不再需要的消息处理器避免在消息处理中创建不必要的对象对于高频消息考虑使用对象池5.2 消息调试技巧创建调试用的消息监视器public class MessageMonitor : IRecipientBrushChangedMessage, IRecipientShapeAddedMessage { public MessageMonitor() { MessageHub.Register(this); } public void Receive(BrushChangedMessage message) { Debug.WriteLine($Brush changed to {message.NewColor}); } public void Receive(ShapeAddedMessage message) { Debug.WriteLine($Shape added: {message.NewShape.GetType().Name}); } }6. 扩展功能实现6.1 实现撤销/重做功能通过消息记录实现命令模式public class UndoRedoService { private readonly StackDrawingMessage _history new(); private readonly StackDrawingMessage _redoStack new(); public UndoRedoService() { MessageHub.RegisterDrawingMessage(this, (r, m) { _history.Push(m); _redoStack.Clear(); }); } public void Undo() { if (_history.TryPop(out var message)) { // 实现反向操作逻辑 _redoStack.Push(message); } } }6.2 多用户协作支持通过集成SignalR实现真正的实时协作public class CollaborationService : IRecipientDrawingMessage { private readonly HubConnection _connection; public CollaborationService() { _connection new HubConnectionBuilder() .WithUrl(https://api.example.com/whiteboardhub) .Build(); MessageHub.Register(this); } public void Receive(DrawingMessage message) { _connection.SendAsync(BroadcastMessage, message); } }7. 项目部署与优化7.1 性能基准测试使用BenchmarkDotNet对关键消息路径进行性能测试[MemoryDiagnoser] public class MessageBenchmarks { private readonly IMessenger _messenger WeakReferenceMessenger.Default; private readonly Receiver _receiver new(); [Benchmark] public void SendSimpleMessage() { _messenger.Send(new SimpleMessage(test)); } private class Receiver : IRecipientSimpleMessage { public void Receive(SimpleMessage message) { } } private record SimpleMessage(string Content); }7.2 打包与分发使用ClickOnce或MSIX进行应用程序打包确保包含所有必要依赖!-- .csproj文件中添加MSIX打包支持 -- PropertyGroup TargetFrameworknet8.0-windows/TargetFramework RuntimeIdentifierswin-x64;win-x86/RuntimeIdentifiers WindowsPackageTypeMSIX/WindowsPackageType /PropertyGroup

相关文章:

C#/.NET 8实战:利用CommunityToolkit.Mvvm的Messenger打造一个简易实时协作白板

C#/.NET 8实战:构建基于CommunityToolkit.Mvvm的实时协作白板系统 在当今分布式协作日益普及的背景下,实现多用户实时交互的白板工具成为许多应用场景的刚需。本文将带您从零开始,利用.NET 8和WPF框架,结合CommunityToolkit.Mvvm中…...

终端美化神器 Oh-My-Posh:终极跨平台提示符定制解决方案

终端美化神器 Oh-My-Posh:终极跨平台提示符定制解决方案 【免费下载链接】oh-my-posh JanDeDobbeleer/oh-my-posh: Oh My Posh 是一个跨平台的终端定制工具,用于增强 PowerShell、Zsh 和 Fish Shell 等终端的视觉效果,提供丰富的主题和样式来…...

避坑指南:Camunda中Execution Listeners和Task Listeners的6个常见误用

Camunda监听器实战避坑指南:6个高频误用场景解析 在Camunda流程引擎的实际开发中,Execution Listeners和Task Listeners是扩展业务流程能力的利器,但也是开发者最容易踩坑的重灾区。许多团队在初步掌握监听器基础用法后,往往会在复…...

从CAN到车载以太网:AUTOSAR网络管理的“跨界”挑战与配置实战

从CAN到车载以太网:AUTOSAR网络管理的异构协同实战 当智能座舱的HUD投影与自动驾驶域控制器的点云处理同时运行时,工程师发现CAN总线上的传统ECU仍在以500kbps的速率发送NM报文,而以太网交换机却已经因为SOME/IP服务发现协议的超时配置陷入了…...

APIPOST 8.x 脚本循环调用接口实战:从踩坑到完美解决OA流程压测问题

APIPOST 8.x 脚本循环调用接口实战:从踩坑到完美解决OA流程压测问题 最近在排查某OA系统偶发的流程异常时,需要模拟真实用户操作进行压力测试。原本考虑使用Jmeter,但环境配置较为复杂,于是尝试了国产工具APIPOST。没想到这次探索…...

Kindle电子书批量下载与DRM去除终极指南:打造你的个人数字图书馆

Kindle电子书批量下载与DRM去除终极指南:打造你的个人数字图书馆 【免费下载链接】Kindle_download_helper Download all your kindle books script. 项目地址: https://gitcode.com/GitHub_Trending/ki/Kindle_download_helper Kindle电子书下载助手是一款强…...

告别微软商店:Win10企业版ThinkPad用户管理电池的终极方案——离线部署Lenovo Vantage全记录

ThinkPad企业级管理:Win10离线部署Lenovo Vantage的技术实践 当企业IT部门选择Windows 10企业版作为标准镜像时,往往会面临一个现实挑战——微软应用商店的缺失使得UWP应用部署变得复杂。作为ThinkPad设备管理的核心工具,Lenovo Vantage的离线…...

Python大模型硬件配置“黑箱”首次公开:头部AIGC公司内部《GPU选型决策树V4.2》泄露版(含量化精度-硬件成本敏感度热力图)

第一章:Python大模型部署硬件要求部署大型语言模型(LLM)在Python生态中日益普及,但其对底层硬件资源的依赖远超传统应用。合理评估并配置硬件是保障推理低延迟、训练可收敛、服务高可用的前提。显存容量与模型规模匹配 主流开源大…...

从NSA到你的桌面:手把手教你安装配置开源逆向神器Ghidra(附JDK17避坑指南)

从NSA到你的桌面:手把手教你安装配置开源逆向神器Ghidra(附JDK17避坑指南) 在软件逆向工程领域,Ghidra的出现无疑是一场革命。这款由美国国家安全局研究局开发并开源的逆向工程框架,以其强大的功能和零成本的优势&…...

2026年3月大模型全景深度解析:国产登顶、百万上下文落地、Agent工业化,AI实用时代全面来临[特殊字符]

🔥个人主页:北极的代码(欢迎来访) 🎬作者简介:java后端学习者 ❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb ✨命运的结局尽可永在,不屈的挑战却不可须臾或…...

南北阁Nanbeige 4.1-3B多语言支持:技术文档翻译与本地化实践

南北阁Nanbeige 4.1-3B多语言支持:技术文档翻译与本地化实践 最近在折腾一些开源项目时,发现不少优秀的工具和框架,文档只有英文版。对于国内开发者来说,这多少是个门槛。虽然现在翻译工具不少,但技术文档的翻译是个精…...

PX4飞控开发实战:如何调试mc_pos_control模块提升多旋翼飞行稳定性

PX4飞控开发实战:如何调试mc_pos_control模块提升多旋翼飞行稳定性 当多旋翼无人机在悬停时出现高频震荡,或是响应指令时显得迟缓笨重,背后往往隐藏着位置控制参数的配置问题。PX4飞控中的mc_pos_control模块作为多旋翼位置控制的核心&#x…...

PyTorch模型量化超快

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 PyTorch模型量化:超快推理的实现路径与未来展望目录PyTorch模型量化:超快推理的实现路径与未来展望 引言…...

解锁官方macOS下载技能:gibMacOS工具实战指南

解锁官方macOS下载技能:gibMacOS工具实战指南 【免费下载链接】gibMacOS Py2/py3 script that can download macOS components direct from Apple 项目地址: https://gitcode.com/gh_mirrors/gi/gibMacOS 还在为无法获取官方macOS安装文件而困扰吗&#xff1…...

植物DNA甲基化检测全攻略:从WGBS到RRBS的实战选择指南

植物DNA甲基化检测技术实战指南:从样本处理到方案优化 在植物表观遗传学研究领域,DNA甲基化检测技术正经历着从实验室探索到农业应用的快速转化。随着高通量测序成本的持续下降和生物信息学工具的日益完善,研究人员现在能够以更高的分辨率和更…...

告别模糊!专业级多显示器显示优化工具全攻略

告别模糊!专业级多显示器显示优化工具全攻略 【免费下载链接】SetDPI 项目地址: https://gitcode.com/gh_mirrors/se/SetDPI 在多显示器办公环境中,你是否经常遇到主副屏幕显示不一致的问题?当4K显示器遇上1080P屏幕,文字…...

深入解析运动控制中的S型速度曲线:从理论到C++实践

1. 为什么需要S型速度曲线 我第一次接触S型速度曲线是在开发工业机械臂控制系统时。当时遇到一个棘手问题:当机械臂以恒定加速度启停时,末端执行器总是会出现明显抖动,导致定位精度下降。后来在导师建议下尝试改用S型速度规划,这个…...

AcousticSense AI应用场景:电台节目音乐分类自动化

AcousticSense AI应用场景:电台节目音乐分类自动化 1. 电台音乐分类的行业痛点 电台节目制作人每天面临一个看似简单却极其耗时的工作:对数以千计的音乐曲目进行流派分类。传统的人工分类方式存在三大痛点: 主观性强:不同音乐编…...

3D动作生成新范式:如何用DiffSynth Studio实现视频到骨架的高效转换

3D动作生成新范式:如何用DiffSynth Studio实现视频到骨架的高效转换 【免费下载链接】DiffSynth-Studio DiffSynth Studio 是一个扩散引擎。我们重组了包括 Text Encoder、UNet、VAE 等在内的架构,保持了与开源社区模型的兼容性,同时提高了计…...

TensorRT黑箱破解指南:从精度谜题到性能优化的技术侦探之旅

TensorRT黑箱破解指南:从精度谜题到性能优化的技术侦探之旅 【免费下载链接】TensorRT NVIDIA TensorRT™ 是一个用于在 NVIDIA GPU 上进行高性能深度学习推理的软件开发工具包(SDK)。此代码库包含了 TensorRT 的开源组件 项目地址: https:…...

【开题答辩全过程】以 基于springboot的校园二手交易平台系统的设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…...

LeetCode 热题 100 之 138. 随机链表的复制 148. 排序链表 23. 合并 K 个升序链表 146. LRU 缓存

138. 随机链表的复制 148. 排序链表 23. 合并 K 个升序链表 146. LRU 缓存 138. 随机链表的复制 /* // Definition for a Node. class Node {int val;Node next;Node random;public Node(int val) {this.val val;this.next null;this.random null;} } */class Solution {pub…...

蓝桥杯基础--时间复杂度

目录 一、 什么是时间复杂度? 大O表示法的两大核心原则: 二、 常见的时间复杂度全解析 1. O(1) - 常数复杂度 2. O(log N) - 对数复杂度 3. O(N) - 线性复杂度 4. O(N log N) - 线性对数复杂度 5. O(N^2) - 平方复杂度 6. O(2^N) 和 O(N!) - 指…...

Jetson Nano三合一串口方案对比:40pin/USB3.0/独立模块到底怎么选?

Jetson Nano三合一串口方案深度评测:硬件选型与实战指南 在嵌入式开发领域,Jetson Nano作为一款高性能边缘计算设备,其串口通信能力直接影响着与各类传感器、控制器(如STM32)的数据交互效率。面对40pin GPIO直连、USB3…...

告别手动刷新!利用Python+Selenium实现问卷星讲座秒抢的实战教程

PythonSelenium自动化实战:高效抢票系统开发指南 从零构建自动化抢票工具 每次看到心仪的讲座或活动开放报名,却总是因为手速不够快而错过?手动刷新页面不仅效率低下,还容易因网络延迟错失良机。本文将带你用Python和Selenium打造…...

Ubuntu-Hyprland高效部署指南:零基础上手Wayland窗口管理器

Ubuntu-Hyprland高效部署指南:零基础上手Wayland窗口管理器 【免费下载链接】Ubuntu-Hyprland Automated Hyprland installer for Ubuntu. NOTE: Repo Branches as per Ubuntu Versions 项目地址: https://gitcode.com/gh_mirrors/ubu/Ubuntu-Hyprland Ubunt…...

新手快速上手Python:Miniconda-Python3.10镜像部署全流程解析

新手快速上手Python:Miniconda-Python3.10镜像部署全流程解析 1. 为什么选择Miniconda-Python3.10 Python作为当下最流行的编程语言之一,以其简洁易读的语法和丰富的生态系统著称。但对于新手来说,环境配置往往是第一个拦路虎。Miniconda-P…...

Moondream2与MySQL结合:构建图像内容数据库

Moondream2与MySQL结合:构建图像内容数据库 1. 引言 想象一下,你手头有成千上万张产品图片,想要快速找到所有包含"红色连衣裙"的图片,或者需要统计所有"户外场景"的商品照片。传统的人工筛选方式不仅耗时费…...

UE5性能调优实战:手把手教你用Unreal Insights揪出卡顿元凶(附完整配置流程)

UE5性能调优实战:手把手教你用Unreal Insights揪出卡顿元凶(附完整配置流程) 当你的UE5项目在特定场景突然掉帧时,那种无力感就像在迷雾中寻找出口。作为经历过数十个项目性能调优的老兵,我总结了一套用Unreal Insight…...

MTKClient技术指南:从底层通信到设备深度控制

MTKClient技术指南:从底层通信到设备深度控制 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient 一、认知铺垫:MTK设备通信的底层逻辑 1.1 为什么需要专用工具&#x…...