从零搭建工业控制系统(一):快速搭建高效开发框架
2026/8/22 20:51:40 网站建设 项目流程

WPF入门:从空白项目到MVVM骨架搭建

这是「从零搭建工业控制系统」系列第1篇。从零开始,手把手搭建一个可维护的WPF项目骨架。


为什么你需要MVVM?

三年前我接手一个半导体设备控制软件项目,打开 MainWindow.xaml.cs,映入眼帘的是2000行代码:按钮点击事件、设备通信、UI更新、定时器逻辑,全堆在一个文件里。

改一个按钮的文字颜色,要在一堆业务逻辑里小心翼翼地找。加一个新功能,牵一发动全身。

MVVM(Model-View-ViewModel)解决的就是这个问题:

  • View(界面):只管长什么样
  • ViewModel(逻辑):只管数据和命令
  • Model(数据):只管业务模型

三者通过数据绑定连接,各司其职,互不干扰。


CommunityToolkit.Mvvm:微软官方的MVVM工具包

传统MVVM写法,每个属性都要手写INotifyPropertyChanged,每个命令都要实现ICommand接口,代码又臭又长。

CommunityToolkit.Mvvm是微软官方维护的轻量级MVVM库,用源代码生成器技术自动生成样板代码。你只需要加一个[ObservableProperty]特性,编译器就帮你搞定一切。

对比一下:

对比项传统手写CommunityToolkit.Mvvm
属性通知15行重复代码1行特性搞定
命令绑定实现ICommand接口1行特性搞定
学习曲线低但代码繁琐最低
包体积无依赖很小,按需引用

第一步:创建项目 + 安装包

1.1 创建WPF项目

打开 Visual Studio 2022 → 新建项目 →WPF应用程序→ 命名MvvmTutorial→ .NET 8。

1.2 安装 CommunityToolkit.Mvvm

工具 → NuGet包管理器 → 程序包管理器控制台

输入:

Install-PackageCommunityToolkit.Mvvm

1.3 建立项目目录结构

MvvmTutorial/ ├── Models/ # 数据模型 ├── ViewModels/ # 视图模型 ├── Views/ # 界面 └── App.xaml # 应用入口

第二步:写你的第一个ViewModel

ViewModels/下新建MainViewModel.cs

usingCommunityToolkit.Mvvm.ComponentModel;usingCommunityToolkit.Mvvm.Input;namespaceMvvmTutorial.ViewModels{// 关键1:partial类,源代码生成器才能工作// 关键2:继承 ObservableObject,自带属性变更通知publicpartialclassMainViewModel:ObservableObject{// 关键3:[ObservableProperty] 自动生成公共属性 + 通知[ObservableProperty]privateintcount=0;[ObservableProperty]privatestringstatus="就绪";// 关键4:[RelayCommand] 自动生成命令属性[RelayCommand]privatevoidIncrement(){Count++;Status=$"已点击{Count}次";}[RelayCommand]privatevoidReset(){Count=0;Status="已重置";}}}

3个关键点解读:

partial class— 必须加,源代码生成器在编译时生成另一半代码。

[ObservableProperty]— 标记在私有字段上,编译器自动生成公共属性(countCount),赋值时自动触发界面刷新。你不用写一行OnPropertyChanged

[RelayCommand]— 标记在方法上,编译器自动生成同名命令属性(IncrementIncrementCommand),可直接绑定到按钮。


第三步:写界面 + 绑定

Views/下新建MainWindow.xaml

<Windowx:Class="MvvmTutorial.Views.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MVVM入门"Height="300"Width="400"><StackPanelVerticalAlignment="Center"HorizontalAlignment="Center"><!-- 显示计数 --><TextBlockText="{Binding Count}"FontSize="48"HorizontalAlignment="Center"/><!-- 显示状态 --><TextBlockText="{Binding Status}"FontSize="16"Margin="0,10"HorizontalAlignment="Center"/><!-- 按钮绑定命令 --><StackPanelOrientation="Horizontal"HorizontalAlignment="Center"Margin="0,20"><ButtonContent="点击+1"Command="{Binding IncrementCommand}"Padding="20,10"Margin="5"/><ButtonContent="重置"Command="{Binding ResetCommand}"Padding="20,10"Margin="5"/></StackPanel></StackPanel></Window>

绑定语法解读:

  • {Binding Count}— 把TextBlock的Text绑定到ViewModel的Count属性,Count变了,界面自动更新
  • {Binding IncrementCommand}— 把Button的Command绑定到ViewModel的IncrementCommand命令,点击按钮自动调用Increment方法

第四步:连接View和ViewModel

这一步是MVVM最关键的一步— 把View和ViewModel绑在一起。

打开MainWindow.xaml.cs

usingMvvmTutorial.ViewModels;usingSystem.Windows;namespaceMvvmTutorial.Views{publicpartialclassMainWindow:Window{publicMainWindow(){InitializeComponent();// 这一行就是MVVM的灵魂DataContext=newMainViewModel();}}}

DataContext = new MainViewModel()— 设置数据上下文后,XAML里所有{Binding xxx}都会去ViewModel里找对应属性和命令。


第五步:运行!

按 F5 运行,你会看到:

  • 点击「点击+1」按钮,数字递增,状态文字更新
  • 点击「重置」按钮,数字归零,状态变为「已重置」

全程没有一行手动刷新UI的代码。这就是MVVM的魔力 — 数据变了,界面自动变。


进阶:带条件判断的命令

实际项目中,按钮不是永远能点的。比如「设备运行中时禁止再点启动」。

CommunityToolkit.Mvvm 原生支持:

publicpartialclassMainViewModel:ObservableObject{[ObservableProperty]privateboolisRunning=false;// CanExecute 方法名 = 命令方法名 + "CanExecute"[RelayCommand(CanExecute=nameof(CanStart))]privatevoidStart(){IsRunning=true;}privateboolCanStart()=>!IsRunning;// 当 IsRunning 变化时,通知命令刷新按钮状态partialvoidOnIsRunningChanged(boolvalue){StartCommand.NotifyCanExecuteChanged();}}

XAML中按钮绑定不变,当IsRunning = true时,按钮自动变灰禁用


真实项目长什么样?

以上是入门示例。来看看我在实际工业项目中怎么用:

// 真实项目:半导体设备控制软件 HomeViewModelpublicpartialclassHomeViewModel:ObservableObject,IDisposable{// === 属性:20+个 [ObservableProperty] ===[ObservableProperty]privateboolisAutoMode=true;[ObservableProperty]privateboolisManualMode=false;[ObservableProperty]privateintalarmCount=0;[ObservableProperty]privatedoublechamberPressure=0;// 腔体压力[ObservableProperty]privatedoubleheater1TempAct=0;// 加热器实际温度// === 命令:模式切换、设备控制 ===[RelayCommand]privatevoidAutoMode(){IsAutoMode=true;IsManualMode=false;}[RelayCommand]privatevoidManualMode(){IsAutoMode=false;IsManualMode=true;}[RelayCommand(CanExecute=nameof(CanRunWhenIdle))]privatevoidRunSequence(){// 执行工艺配方...}privateboolCanRunWhenIdle()=>!_commandService.IsBusy;}

对应的XAML绑定:

<!-- 模式切换控件 --><operator:AutoManualSwitchIsLeftActive="{Binding IsAutoMode, Mode=OneWay}"LeftCommand="{Binding AutoModeCommand}"RightCommand="{Binding ManualModeCommand}"/><!-- 报警控件 --><operator:WarningAlarmCount="{Binding AlarmCount}"WarningCommand="{Binding WarningCommand}"/>

一个 ViewModel 管理几十个属性和命令,但代码依然清晰可读。这就是 CommunityToolkit.Mvvm 的威力。


本篇小结

知识点关键代码
属性自动通知[ObservableProperty] private int count;
命令自动生成[RelayCommand] private void DoSomething()
命令条件判断[RelayCommand(CanExecute = nameof(CanDo))]
连接View和VMDataContext = new MainViewModel();
XAML绑定{Binding Count}/{Binding DoSomethingCommand}

5个核心知识点,搭建一个完整的MVVM骨架。


下期预告

第2篇:MVVM实战 — RelayCommand绑定按钮到ViewModel方法

我们将深入命令系统:异步命令、带参数命令、命令的CanExecute动态刷新,以及在真实项目中如何用反射批量通知命令状态。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询