WPF中的MVVM框架

一、MVVM 模式的核心概念

1. Model(模型)

  • 表示应用程序的数据模型,通常是一个简单的类,包含数据属性和业务逻辑。

  • 不依赖于 UI,可以独立于 WPF 使用。

2. View(视图)

  • 是用户界面,通常由 XAML 文件定义。

  • 通过数据绑定与 ViewModel 交互,不直接与 Model 交互。

3. ViewModel(视图模型)

  • 是 Model 和 View 之间的中间层,负责处理业务逻辑和用户交互。

  • 提供数据绑定的接口(通常是 INotifyPropertyChanged),并将 Model 的数据暴露给 View。

  • 可以包含命令(ICommand)来处理用户的操作。

二、实现步骤

1. 定义 Model

Model 是一个简单的类,包含数据属性和业务逻辑。例如,定义一个 Person 类:

复制代码
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

2. 创建 ViewModel

ViewModel 是 MVVM 的核心,它需要实现 INotifyPropertyChanged 接口,以便通知 View 数据的变化。同时,ViewModel 会包含 Model 的实例,并提供绑定到 View 的属性。

实现 INotifyPropertyChanged
复制代码
using System.ComponentModel;
using System.Runtime.CompilerServices;
​
public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
​
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
创建具体的 ViewModel
复制代码
public class MainViewModel : ViewModelBase
{
    private Person _person;
​
    public MainViewModel()
    {
        // 初始化 Model
        _person = new Person { Name = "John Doe", Age = 30 };
    }
​
    // 提供绑定到 View 的属性
    public string Name
    {
        get => _person.Name;
        set
        {
            if (_person.Name != value)
            {
                _person.Name = value;
                OnPropertyChanged();
            }
        }
    }
​
    public int Age
    {
        get => _person.Age;
        set
        {
            if (_person.Age != value)
            {
                _person.Age = value;
                OnPropertyChanged();
            }
        }
    }
}

3. 创建 View

View 是 XAML 文件,通过数据绑定与 ViewModel 交互。在 XAML 中,需要设置 DataContext,并将控件的属性绑定到 ViewModel 的属性。

定义 XAML 文件
复制代码
<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MVVM Example" Height="200" Width="300">
    <Grid>
        <StackPanel Margin="10">
            <TextBlock Text="Name:" />
            <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
​
            <TextBlock Text="Age:" />
            <TextBox Text="{Binding Age, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
​
            <Button Content="Save" Command="{Binding SaveCommand}" Margin="0,10,0,0" />
        </StackPanel>
    </Grid>
</Window>
设置 DataContext

在代码后台(MainWindow.xaml.cs)中,设置 DataContext 为 ViewModel 的实例:

复制代码
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

4. 实现命令(Command)

在 MVVM 中,按钮的点击事件通常通过命令(ICommand)来处理。可以在 ViewModel 中定义一个命令属性。

定义命令类
复制代码
using System;
using System.Windows.Input;
​
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;
​
    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }
​
    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute();
    }
​
    public void Execute(object parameter)
    {
        _execute();
    }
​
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}
在 ViewModel 中使用命令
复制代码
public class MainViewModel : ViewModelBase
{
    private Person _person;
​
    public MainViewModel()
    {
        _person = new Person { Name = "John Doe", Age = 30 };
    }
​
    public string Name
    {
        get => _person.Name;
        set
        {
            if (_person.Name != value)
            {
                _person.Name = value;
                OnPropertyChanged();
            }
        }
    }
​
    public int Age
    {
        get => _person.Age;
        set
        {
            if (_person.Age != value)
            {
                _person.Age = value;
                OnPropertyChanged();
            }
        }
    }
​
    // 定义命令
    public ICommand SaveCommand { get; }
​
    public MainViewModel()
    {
        _person = new Person { Name = "John Doe", Age = 30 };
        SaveCommand = new RelayCommand(Save);
    }
​
    private void Save()
    {
        // 处理保存逻辑
        MessageBox.Show("Data saved!");
    }
}

5. 完整的绑定

在 XAML 中绑定命令:

复制代码
<Button Content="Save" Command="{Binding SaveCommand}" Margin="0,10,0,0" />

三、总结

通过以上步骤,我们实现了一个简单的 MVVM 示例:

  1. 定义了 Model(Person 类)。

  2. 创建了 ViewModel(MainViewModel 类),实现了 INotifyPropertyChanged 和命令。

  3. 定义了 View(XAML 文件),并通过数据绑定与 ViewModel 交互。

  4. 使用命令处理用户操作。

这种模式将 UI 和业务逻辑分离,提高了代码的可维护性和可测试性。

相关推荐
向夏威夷 梦断明暄1 天前
【GUI-Agent】阿里通义MAI-UI 代码阅读(2)--- 实现
ui
icestone20002 天前
彻底解决 RDP 断开后 UI 自动化(RPA)失效问题:三步让机器人后台无缝运行
ui·自动化·rpa
Kim.Li2 天前
格式塔设计原则全解析:12项核心原则在 UI/UX 中的实战应用指南
ui·产品经理·ux·视觉设计·交互设计
jin1233222 天前
HarmonyOS ArkTS API 24实现声明式 UI 框架与 @Builder 组件复用模式构建三标签页智能账单应用
ui·华为·harmonyos
Getflare3 天前
前端 + UI 设计 + AI:这不是三个工种,是一个新三角能力模型(附自检清单)
前端·人工智能·ui
达子6663 天前
第9章_HarmonyOs图解 用Java开发UI
java·ui·harmonyos
<小智>3 天前
鸿蒙多功能工具箱开发实战(二十四)-单元测试与自动化测试
ui·华为·harmonyos
早点睡啊Y4 天前
深入学LangChain官方文档(二十二):Frontend 高级形态——Headless Tools、Time Travel 与 Generative UI
ui·langchain·状态模式
<小智>4 天前
鸿蒙多功能工具箱开发实战(二十)-性能优化与打包发布
ui·华为·harmonyos
薛定谔的猫-菜鸟程序员4 天前
一个 Skill 如何让大模型拥有专业 UI 能力?——ui-ux-pro-max 架构深度拆解与 Skill 设计方法论
人工智能·ui