WPF 上位机用 MVVM 架构:让界面和逻辑彻底分开

丁丁智造 · 2026-08-05
WPF 上位机用 MVVM 架构:让界面和逻辑彻底分开
导读:WPF 做工业上位机,代码全堆在按钮事件里会越来越难维护。本文讲清 MVVM 的 Model/View/ViewModel 分工和数据绑定,给出可落地的项目结构。

为什么要用 MVVM

不用 MVVM 的 WPF,典型问题是:按钮点击事件里既读 PLC、又改界面、又写数据库,通讯协议一改,界面代码跟着崩。MVVM 的价值是界面(View)和业务逻辑(ViewModel)分离,逻辑可测试、界面可替换。

三者分工

  • Model:设备、点位、数据模型,以及通讯/存储服务(与界面无关)
  • View:XAML 界面,只负责展示和绑定,后台代码尽量不写业务
  • ViewModel:连接两者,暴露界面要绑定的属性和命令,内部调用 Model

核心机制:数据绑定与通知

ViewModel 实现 INotifyPropertyChanged,属性变化时界面自动刷新;界面操作通过 ICommand 绑定到 ViewModel 方法,不在 XAML.cs 里写业务。

public class MainViewModel : INotifyPropertyChanged
{
    private double _temperature;
    public double Temperature
    {
        get => _temperature;
        set { _temperature = value; OnPropertyChanged(); }
    }
    public ICommand StartCommand { get; }
    // ...
}

XAML 里只做绑定:Text="{Binding Temperature}"Command="{Binding StartCommand}"

推荐项目结构

Models/        数据模型
Services/      通讯服务、存储服务(接口化,可替换/可Mock)
ViewModels/    各页面 ViewModel
Views/         XAML 页面
Common/        转换器、事件聚合、基类

与通讯层配合

通讯服务在后台线程持续更新点位缓存,ViewModel 只订阅缓存变化并刷新绑定属性。注意:非 UI 线程更新绑定属性时,WPF 绑定机制会自动调度到 UI 线程,但集合(ObservableCollection)更新仍需 Dispatcher。

状态灯的做法

用值转换器(Converter)把状态枚举转成颜色:运行绿、报警黄、故障红、离线灰,XAML 绑定状态即可,不在后台代码里逐个改控件颜色。

落地建议

  1. 先写一个 ViewModelBase 封装 PropertyChanged
  2. 通讯服务抽接口,开发时用 MockService 假数据,没 PLC 也能做界面
  3. 用依赖注入把服务注入 ViewModel
  4. 业务逻辑放 ViewModel/Service,做到 ViewModel 可单元测试

前期多搭一层架子,换来的是界面、通讯、业务各自独立演进,这正是上位机能维护十年的基础。