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

CommunityToolkit.Mvvm 重构激光直写控制软件

使用 CommunityToolkit.Mvvm 库重新设计激光直写控制软件的框架,展示现代 MVVM 实现方式。

一、项目结构

LaserDirectWriteApp/
├── Models/
│   ├── LaserParameters.cs
│   ├── MotionParameters.cs
│   └── SystemStatus.cs
├── ViewModels/
│   ├── MainViewModel.cs
│   ├── LaserControlViewModel.cs
│   ├── MotionControlViewModel.cs
│   └── PreviewViewModel.cs
├── Views/
│   ├── MainWindow.xaml
│   ├── LaserControlView.xaml
│   ├── MotionControlView.xaml
│   └── PreviewView.xaml
├── Services/
│   ├── ILaserService.cs
│   ├── IMotionService.cs
│   ├── LaserService.cs
│   └── MotionService.cs
├── Converters/
│   └── BooleanToStatusConverter.cs
└── App.xaml

 

二、核心实现

1. 安装必要包

dotnet add package CommunityToolkit.Mvvm
dotnet add package Microsoft.Extensions.DependencyInjection

2. 应用入口 (App.xaml.cs)

using Microsoft.Extensions.DependencyInjection;
using CommunityToolkit.Mvvm.DependencyInjection;public partial class App : Application
{public App(){// 配置依赖注入Ioc.Default.ConfigureServices(new ServiceCollection().AddSingleton<ILaserService, LaserService>().AddSingleton<IMotionService, MotionService>().AddTransient<MainViewModel>().AddTransient<LaserControlViewModel>().AddTransient<MotionControlViewModel>().AddTransient<PreviewViewModel>().BuildServiceProvider());}protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);var mainWindow = new MainWindow{DataContext = Ioc.Default.GetRequiredService<MainViewModel>()};mainWindow.Show();}
}

3. 主视图模型 (MainViewModel.cs)

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;public partial class MainViewModel : ObservableObject
{private readonly ILaserService _laserService;private readonly IMotionService _motionService;[ObservableProperty]private string _statusMessage = "系统就绪";[ObservableProperty][NotifyPropertyChangedFor(nameof(IsDisconnected))]private bool _isConnected;public bool IsDisconnected => !IsConnected;public MainViewModel(ILaserService laserService, IMotionService motionService){_laserService = laserService;_motionService = motionService;// 订阅设备状态消息WeakReferenceMessenger.Default.Register<DeviceStatusMessage>(this, (r, m) =>{StatusMessage = m.Message;});}[RelayCommand]private async Task ConnectAsync(){try{WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("正在连接设备..."));await Task.WhenAll(Task.Run(() => _motionService.Connect()),Task.Run(() => _laserService.Connect()));IsConnected = true;WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("设备连接成功"));}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"连接失败: {ex.Message}"));}}[RelayCommand(CanExecute = nameof(IsConnected))]private void Disconnect(){try{WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("正在断开设备..."));_laserService.Disconnect();_motionService.Disconnect();IsConnected = false;WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("设备已断开"));}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"断开失败: {ex.Message}"));}}[RelayCommand]private void Exit(){if (IsConnected) Disconnect();Application.Current.Shutdown();}
}public record DeviceStatusMessage(string Message);

4. 激光控制视图模型 (LaserControlViewModel.cs)

public partial class LaserControlViewModel : ObservableObject
{private readonly ILaserService _laserService;[ObservableProperty]private LaserParameters _parameters = new();public LaserControlViewModel(ILaserService laserService){_laserService = laserService;// 初始化默认值Parameters = new LaserParameters{Power = 30,Frequency = 1000,PulseWidth = 100};}[RelayCommand]private void ToggleLaser(){try{_laserService.SetEnabled(Parameters.IsEnabled);WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"激光器已{(Parameters.IsEnabled ? "开启" : "关闭"}"));}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"激光控制失败: {ex.Message}"));}}[RelayCommand]private void ApplySettings(){try{_laserService.SetPower(Parameters.Power);_laserService.SetFrequency(Parameters.Frequency);_laserService.SetPulseWidth(Parameters.PulseWidth);WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("激光参数已更新"));}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"参数设置失败: {ex.Message}"));}}
}

5. 运动控制视图模型 (MotionControlViewModel.cs)

public partial class MotionControlViewModel : ObservableObject
{private readonly IMotionService _motionService;[ObservableProperty]private MotionParameters _parameters = new();public MotionControlViewModel(IMotionService motionService){_motionService = motionService;// 订阅位置更新_motionService.PositionUpdated += OnPositionUpdated;}private void OnPositionUpdated(object? sender, PositionUpdatedEventArgs e){Parameters.XPosition = e.X;Parameters.YPosition = e.Y;Parameters.ZPosition = e.Z;}[RelayCommand(CanExecute = nameof(CanMove))]private async Task MoveAsync(){try{await _motionService.MoveTo(Parameters.XTarget,Parameters.YTarget,Parameters.ZTarget);}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"移动失败: {ex.Message}"));}}private bool CanMove() => !_motionService.IsMoving;[RelayCommand]private async Task HomeAsync(){try{await _motionService.Home();WeakReferenceMessenger.Default.Send(new DeviceStatusMessage("已回原点"));}catch (Exception ex){WeakReferenceMessenger.Default.Send(new DeviceStatusMessage($"回原点失败: {ex.Message}"));}}
}

6. 主窗口视图 (MainWindow.xaml)

<Window x:Class="LaserDirectWriteApp.Views.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:LaserDirectWriteApp.Views"mc:Ignorable="d"Title="激光直写控制系统" Height="800" Width="1200"><DockPanel><!-- 顶部菜单 --><Menu DockPanel.Dock="Top"><MenuItem Header="文件"><MenuItem Command="{Binding ExitCommand}" Header="退出"/></MenuItem><MenuItem Header="设备"><MenuItem Command="{Binding ConnectCommand}" Header="连接"/><MenuItem Command="{Binding DisconnectCommand}" Header="断开" IsEnabled="{Binding IsConnected}"/></MenuItem></Menu><!-- 状态栏 --><StatusBar DockPanel.Dock="Bottom"><StatusBarItem><TextBlock Text="{Binding StatusMessage}"/></StatusBarItem></StatusBar><!-- 主内容区 --><TabControl><TabItem Header="激光控制"><local:LaserControlView DataContext="{Binding Source={x:Static Ioc.Default}, Path=GetRequiredService{LaserControlViewModel}}"/></TabItem><TabItem Header="运动控制"><local:MotionControlView DataContext="{Binding Source={x:Static Ioc.Default}, Path=GetRequiredService{MotionControlViewModel}}"/></TabItem><TabItem Header="预览"><local:PreviewView DataContext="{Binding Source={x:Static Ioc.Default}, Path=GetRequiredService{PreviewViewModel}}"/></TabItem></TabControl></DockPanel>
</Window>

三、CommunityToolkit.Mvvm 优势体现

  1. 极简代码:使用 [ObservableProperty] 和 [RelayCommand] 大幅减少样板代码

    • 传统方式需要 20+ 行代码的属性现在只需 1 行

    • 命令实现从 10+ 行减少到 1 行属性

  2. 类型安全:源码生成器保证编译时类型检查

[ObservableProperty]
private string _name; // 自动生成 Name 属性,带通知功能

现代化异步支持

[RelayCommand]
private async Task LoadDataAsync()
{// 自动处理异步操作和异常
}

弱引用消息:避免内存泄漏

WeakReferenceMessenger.Default.Register<MyMessage>(this, (r, m) => { });

依赖注入集成

// 配置
Ioc.Default.ConfigureServices(services);// 使用
var vm = Ioc.Default.GetRequiredService<MyViewModel>();

四、扩展建议

  1. 添加验证:结合 DataAnnotations 实现属性验证

[ObservableProperty]
[Required(ErrorMessage = "功率不能为空")]
[Range(0, 100, ErrorMessage = "功率必须在0-100之间")]
private double _power;

使用记录类型:为消息定义不可变模型

public record PositionMessage(double X, double Y, double Z);

添加单元测试:利用轻量级特性简化测试

var vm = new LaserControlViewModel(mockLaserService);
vm.ToggleLaserCommand.Execute(null);
mockLaserService.Verify(x => x.SetEnabled(true));

这个实现展示了如何使用 CommunityToolkit.Mvvm 构建现代化、高性能的激光直写控制软件,相比传统 MVVM 实现代码量减少约 40%,同时提高了可维护性和类型安全性。

http://www.lqws.cn/news/516115.html

相关文章:

  • STM32G070x 单片机项目代码解析:基于 HAL 库的嵌入式系统开发
  • oracle 删除数据
  • 【计算机网络】第二章:物理层
  • 如何轻松恢复出厂设置 Android 手机
  • 华为云Flexus+DeepSeek征文|基于Dify+ModelArts打造智能客服工单处理系统
  • 如何将FPGA设计验证效率提升1000倍以上(1)
  • 云原生与人工智能的融合:从弹性架构到智能运维的IT新范式
  • HCIA-OSPF基础
  • 【机器学习深度学习】张量基本操作
  • AR/VR 显示画质失真?OAS 体全息光栅案例来解决
  • Git知识梳理常见问题
  • Linux - firewall
  • 二叉树理论基础
  • python的kivy框架界面布局方法详解
  • 智能手机是人类的寄生物
  • 高通手机跑AI系列之——人脸变化算法
  • 机器学习复习
  • 《MySQL 技术内幕(第5版)》逐章精华笔记第七章
  • 【学习笔记】3.3 Decoder-Only PLM
  • 芯片战争升级:进口马维尔VS自研中兴微,解码格行随身WiFi性能密码,格行随身WIFI到底行不行
  • 《从0到1:C/C++音视频开发自学指南》
  • 大语言模型的通用局限性与全球技术演进
  • 【智能协同云图库】智能协同云图库第二弹:用户管理系统后端设计与接口开发
  • CSS基础3
  • 将Python Tkinter程序转换为手机可运行的Web应用 - 详细教程
  • Nginx + Tomcat 负载均衡搭建
  • 数字孪生技术引领UI前端设计潮流:沉浸式体验的新篇章
  • CVPR-2025 | 上交拥挤无序环境下的具身导航最新基准!RoboSense:以机器人为中心的具身感知与导航大规模数据集
  • POJ3050-Hopscotch(穷竭搜索:DFS)
  • 构造函数和析构函数