欢迎光临
我们一直在努力

MVVM(Model-View-ViewModel)模式是 WPF(Windows Presentation Foundation)、Silverlight、UWP 以及其他现代 UI 框架

MVVM(Model-View-ViewModel)模式是 WPF(Windows Presentation Foundation)、Silverlight、UWP 以及其他现代 UI 框架(如 Xamarin、MAUI)中广泛使用的一种架构模式。它旨在实现 关注点分离(Separation of Concerns),将界面逻辑(View)、业务逻辑(ViewModel)和数据(Model)解耦,提高代码的可维护性、可测试性和可扩展性。以下是对 MVVM 模式的详细讲解,结合 WPF 框架和提供的代码示例(ParamSetupModel),涵盖核心概念、实现方式、优点、缺点以及实际应用。


一、MVVM 模式的核心组成部分

MVVM 模式由以下三个核心部分组成:

  • Model(模型):

    • 定义:Model 表示应用程序的数据和业务逻辑的底层实现,通常与数据存储(如数据库、文件)或外部服务交互。
    • 特点:
      • 包含数据实体(如用户、订单)或业务逻辑(如计算、验证)。
      • 不依赖于 UI,独立于 View 和 ViewModel。
      • 通常是简单的 POCO(Plain Old CLR Object)类或与数据访问层交互的类。
    • 示例:
      在提供的 ParamSetupModel 类中,StopConditionModel 可能是一个独立的 Model 类,存储停止条件的数据。ParamSetupModel 本身也部分扮演 Model 角色,存储测试参数(如 ProjectTcavg、ProjectCurrent)。
  • View(视图):

    • 定义:View 是用户界面,负责显示数据和接收用户输入,通常由 XAML 文件(在 WPF 中)定义。
    • 特点:
      • 通过数据绑定(Data Binding)与 ViewModel 交互,显示 ViewModel 中的数据。
      • 使用命令(Command)处理用户操作(如按钮点击)。
      • 尽量不包含业务逻辑,仅负责 UI 渲染和用户交互。
    • 示例:
      在 WPF 中,View 是一个 XAML 文件,可能包含 ComboBox(绑定到 ProjectModes)、Button(绑定到 ProjectHistoryBtnVisible)等控件。
  • ViewModel(视图模型):

    • 定义:ViewModel 是 View 和 Model 之间的桥梁,负责处理 UI 逻辑、协调数据和命令。
    • 特点:
      • 提供数据属性(与 View 绑定)和命令(响应用户操作)。
      • 实现 INotifyPropertyChanged 接口,支持数据变更通知。
      • 与 Model 交互,获取或更新数据。
      • 不直接引用 View,保持松耦合。
    • 示例:
      ParamSetupModel 继承自 Prism.Mvvm.BindableBase,通过 SetProperty 实现属性通知,扮演 ViewModel 的角色(尽管其名称包含 “Model”,但其功能更偏向 ViewModel)。

  • 二、MVVM 模式的实现机制

    MVVM 模式在 WPF 中依赖以下核心机制:

  • 数据绑定(Data Binding):

    • WPF 的数据绑定允许 View 的控件属性(如 TextBlock.Text)绑定到 ViewModel 的属性(如 ProjectPercentageText)。
    • 数据绑定支持单向、双向和一次性绑定:
      • 单向绑定:ViewModel → View(如显示 ProjectTcavg)。
      • 双向绑定:ViewModel ↔ View(如 ComboBox 的 SelectedItem 绑定到 ProjectMode)。
      • 一次性绑定:初始化时绑定一次(如静态配置)。
    • 示例:<TextBlock Text="{Binding ProjectPercentageText}" />
  • 属性变更通知(INotifyPropertyChanged):

    • ViewModel 属性通过实现 INotifyPropertyChanged 接口通知 View 数据变化。
    • Prism 的 BindableBase 提供了 SetProperty 方法,简化了属性通知的实现。
    • 示例(从 ParamSetupModel):private string _projectTcavg;
      public string ProjectTcavg
      {
      get { return _projectTcavg; }
      set { SetProperty(ref _projectTcavg, value); }
      }

      当 ProjectTcavg 改变时,SetProperty 触发 PropertyChanged 事件,UI 自动更新。

  • 命令(Command):

    • WPF 的命令机制(如 ICommand 接口)允许 ViewModel 处理用户操作(如按钮点击)。
    • Prism 提供 DelegateCommand,简化命令实现。
    • 示例:public DelegateCommand ViewHistoryCommand { get; } = new DelegateCommand(() =>
      {
      // 处理查看历史曲线的逻辑
      });

      XAML 绑定:<Button Command="{Binding ViewHistoryCommand}" Content="View History" />

  • 依赖注入与服务:

    • MVVM 模式通常结合依赖注入(Dependency Injection)来解耦 ViewModel 和 Model。
    • Prism 提供 DI 容器(如 Unity、MEF),便于注入服务(如数据访问服务)。
    • 示例:
      ParamSetupModel 可能通过构造函数注入 StopConditionModel 或数据服务。
  • 数据模板(DataTemplate)与转换器(IValueConverter):

    • 数据模板定义数据在 UI 中的显示方式。
    • 转换器用于在绑定时转换数据(如将 bool 转换为 Visibility)。
    • 示例:<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
      <Button Visibility="{Binding IsOpenBigFlow, Converter={StaticResource BoolToVisibility}}" />


  • 三、MVVM 模式的优点

  • 关注点分离:

    • View(UI)、ViewModel(逻辑)、Model(数据)分离,代码结构清晰。
    • 便于团队协作:UI 设计师专注于 XAML,前端开发者专注于 ViewModel,后端开发者专注于 Model。
  • 可测试性:

    • ViewModel 不依赖 View,可以通过单元测试验证业务逻辑。
    • 例如,测试 ParamSetupModel 的 ProjectMethod setter 逻辑是否正确更新 ProjectModes。
  • 可维护性:

    • 逻辑集中在 ViewModel,易于修改和扩展。
    • 例如,添加新的 ProjectMethod 选项只需更新 ParamSetupModel 的 setter 逻辑。
  • 可重用性:

    • ViewModel 和 Model 可在不同 View 中重用。
    • 例如,ParamSetupModel 可用于桌面 WPF 应用或移动端应用。
  • 动态 UI 更新:

    • 数据绑定和属性通知确保 UI 实时反映 ViewModel 的变化。
    • 例如,ProjectModeVisible 改变时,UI 控件自动显示或隐藏。

  • 四、MVVM 模式的缺点

  • 复杂性:

    • 对于小型项目,MVVM 可能引入过多的样板代码(如属性通知、命令)。
    • 例如,ParamSetupModel 中的多个 Visibility 属性增加了代码量。
  • 学习曲线:

    • MVVM 依赖数据绑定、命令等 WPF 机制,初学者可能需要时间掌握。
    • 使用 Prism 等框架进一步提高了学习成本。
  • 性能开销:

    • 数据绑定和属性通知可能在复杂 UI 中引入性能问题,尤其是绑定到大量动态数据时。
    • 例如,ProjectModes 的频繁更新可能触发多次 UI 重绘。
  • 调试困难:

    • 数据绑定错误(如拼写错误)在编译时难以发现,可能导致运行时问题。
    • 例如,若 XAML 中绑定到 ProjectMode 拼写为 ProjectModes,不会报错但 UI 不更新。

  • 五、MVVM 在提供的代码中的应用

    ParamSetupModel 类展示了 MVVM 模式在 WPF 中的典型应用,以下是具体分析:

  • ViewModel 角色:

    • ParamSetupModel 继承自 BindableBase,实现属性通知,适合作为 ViewModel。
    • 属性(如 ProjectMethod、ProjectMode)通过 SetProperty 实现数据绑定。
    • 例如:public string ProjectMethod
      {
      get { return _projectMethod; }
      set
      {
      ProjectModes.Clear();
      if ("PC" == value)
      {
      ProjectModes.Add("Fixed Ic");
      ProjectModes.Add("Fixed △Tvj");
      ProjectModes.Add("Fixed Pon");
      }
      SetProperty(ref _projectMethod, value);
      }
      }

      当 ProjectMethod 改变时,ProjectModes 更新并通知 UI(如 ComboBox)。

  • UI 控制:

    • 属性如 ProjectModeVisible、ProjectZthRthBtnVisible 使用 Visibility 类型,绑定到 UI 控件的 Visibility 属性。
    • 示例 XAML:<ComboBox Visibility="{Binding ProjectModeVisible}"
      ItemsSource="{Binding ProjectModes}"
      SelectedItem="{Binding ProjectMode}" />

  • 动态数据集合:

    • ProjectModes 使用 ObservableCollection<string>,支持动态更新。
    • 当 ProjectMethod 改变时,ProjectModes.Clear() 和 Add 方法触发集合变更通知,UI 自动刷新。
  • JSON 序列化:

    • 使用 [JsonIgnore] 注解(如 ProjectModeVisible),避免序列化 UI 相关属性,保持 Model 的纯粹性。
  • 逻辑集中:

    • ProjectMethod 的 setter 包含复杂逻辑,控制多个属性的状态(如 ProjectModeVisible、ProjectPCResultListVisible)。
    • 这种设计将 UI 逻辑集中在 ViewModel 中,View 仅负责显示。

  • 六、MVVM 的实际应用场景

    MVVM 模式在以下场景中特别有用:

  • 复杂 UI 应用:

    • 如工业控制软件(PowerCycling 项目可能是一个工业测试应用),需要动态更新 UI(如进度条、温度显示)。
    • ParamSetupModel 的 ProjectPercentage 和 ProjectPercentageText 可绑定到进度条和文本显示。
  • 数据驱动 UI:

    • 需要实时显示变化的数据(如传感器数据)。
    • 例如,ProjectTcavg、ProjectPonavg 可绑定到实时监控界面。
  • 跨平台开发:

    • ViewModel 和 Model 可复用于不同平台(如 WPF、UWP、MAUI)。
    • ParamSetupModel 的逻辑可复用于其他 UI 框架,只需更换 View。
  • 单元测试:

    • ViewModel 的逻辑(如 ProjectMethod 的 setter)可通过单元测试验证。
    • 示例测试:[Test]
      public void ProjectMethod_SetToPC_UpdatesProjectModes()
      {
      var model = new ParamSetupModel();
      model.ProjectMethod = "PC";
      Assert.Contains("Fixed Ic", model.ProjectModes);
      Assert.AreEqual(Visibility.Visible, model.ProjectModeVisible);
      }


  • 七、MVVM 的最佳实践

    结合 ParamSetupModel 和 WPF 开发经验,以下是 MVVM 模式的最佳实践:

  • 保持 ViewModel 纯粹:

    • ViewModel 不应直接引用 View 或 UI 元素(如 Window、Button)。
    • ParamSetupModel 的 Visibility 属性虽然与 UI 相关,但通过数据绑定间接控制,符合 MVVM。
  • 最小化逻辑:

    • 将复杂逻辑移到服务类或 Model 中。例如,ProjectMethod 的 setter 逻辑可提取到单独的服务类:public class ProjectMethodService
      {
      public void UpdateModes(string method, ObservableCollection<string> modes, ref Visibility modeVisible)
      {
      modes.Clear();
      if (method == "PC")
      {
      modes.Add("Fixed Ic");
      modeVisible = Visibility.Visible;
      }
      else
      {
      modeVisible = Visibility.Collapsed;
      }
      }
      }

  • 使用命令:

    • 为用户操作(如按钮点击)定义命令,而不是在 View 中处理事件。
    • 例如,为 ProjectHistoryBtnVisible 对应的按钮添加 DelegateCommand。
  • 类型安全:

    • 使用枚举替代字符串(如 ProjectMethod 和 ProjectMode)。
    • 示例:public enum TestMethod { PC, KCoefficient, ThermalResistance }
  • 错误处理:

    • 在 ViewModel 中添加验证逻辑,防止非法输入。
    • 例如,验证 ProjectMethod 是否为有效值。
  • 使用 Prism 或其他 MVVM 框架:

    • Prism 提供 BindableBase、DelegateCommand 等工具,简化 MVVM 实现。
    • 其他框架(如 MVVM Light、Caliburn.Micro)也可考虑。

  • 八、结合 ParamSetupModel 的改进建议

    基于 MVVM 模式,以下是对 ParamSetupModel 的改进建议:

  • 分离 Model 和 ViewModel:

    • 当前 ParamSetupModel 混合了 Model 和 ViewModel 的职责。建议拆分为:
      • ProjectSettings(Model):存储数据(如 ProjectTcavg、ProjectCurrent)。
      • ParamSetupViewModel:处理 UI 逻辑(如 ProjectModeVisible)。
    • 示例:public class ProjectSettings
      {
      public string ProjectMethod { get; set; }
      public string ProjectMode { get; set; }
      public bool IsOpenBigFlow { get; set; }
      }

      public class ParamSetupViewModel : BindableBase
      {
      private readonly ProjectSettings _settings;
      public ParamSetupViewModel(ProjectSettings settings)
      {
      _settings = settings;
      }

      public string ProjectMethod
      {
      get => _settings.ProjectMethod;
      set
      {
      _settings.ProjectMethod = value;
      ProjectModes.Clear();
      if (value == "PC")
      {
      ProjectModes.Add("Fixed Ic");
      ProjectModeVisible = Visibility.Visible;
      }
      SetProperty(ref _settings.ProjectMethod, value);
      }
      }
      }

  • 使用枚举:

    • 将 ProjectMethod 和 ProjectMode 改为枚举:public enum TestMethod { PC, KCoefficient, ThermalResistance }
      public enum ControlMode { FixedIc, FixedDeltaTvj, FixedPon }

  • 添加命令:

    • 为按钮(如历史曲线按钮)添加 DelegateCommand:public DelegateCommand ViewHistoryCommand { get; } = new DelegateCommand(() =>
      {
      // 打开历史曲线窗口
      }, () => ProjectHistoryBtnVisible == Visibility.Visible);

  • 优化类型:

    • 将 ProjectTcavg 等改为 double 类型,结合转换器显示格式化文本:<TextBlock Text="{Binding ProjectTcavg, StringFormat={}{0:F2} °C}" />
  • 异常处理:

    • 在 ProjectMethod 的 setter 中添加验证:public string ProjectMethod
      {
      get => _projectMethod;
      set
      {
      if (!new[] { "PC", "K系数", "热阻" }.Contains(value))
      throw new ArgumentException("Invalid ProjectMethod");
      // 其余逻辑
      }
      }


  • 九、总结

    MVVM 模式通过分离 View、ViewModel 和 Model,提供了清晰的代码结构,增强了 WPF 应用的可维护性和可测试性。ParamSetupModel 是一个典型的 ViewModel 实现,结合 Prism 的 BindableBase 和 WPF 的数据绑定,实现了动态 UI 更新和复杂逻辑控制。通过优化类型、分离职责和添加命令,可以进一步提升代码质量。

    赞(0)
    未经允许不得转载:171主机测评 » MVVM(Model-View-ViewModel)模式是 WPF(Windows Presentation Foundation)、Silverlight、UWP 以及其他现代 UI 框架
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址