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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2447561.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!