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 和业务逻辑分离,提高了代码的可维护性和可测试性。

相关推荐
I'm Jie3 小时前
Swagger UI 本地化部署,解决 FastAPI Swagger UI 依赖外部 CDN 加载失败问题
python·ui·fastapi·swagger·swagger ui
爱学习的程序媛4 小时前
【Web前端】优化Core Web Vitals提升用户体验
前端·ui·web·ux·用户体验
爱学习的程序媛4 小时前
【Web前端】前端用户体验优化全攻略
前端·ui·交互·web·ux·用户体验
紫丁香5 小时前
Selenium自动化测试详解1
python·selenium·测试工具·ui
GISer_Jing5 小时前
前端组件库——shadcn/ui:轻量、自由、可拥有,解锁前端组件库的AI时代未来
前端·人工智能·ui
rjc_lihui8 小时前
IntelliSense: 无法打开 源 文件 “ui_mainwindow.h“ demo\qtdemosrc\mainwindow
ui
老星*1 天前
Lucide Icons:开源、轻量、设计师友好的现代图标库
ui·开源·github
Swift社区1 天前
AI 驱动 UI:鸿蒙 ArkUI 的新可能
人工智能·ui·harmonyos
Feng-licong1 天前
告别手写 UI:当 Google Stitch 遇上 Flutter,2026 年的“Vibe Coding”开发流
flutter·ui
一字白首1 天前
微信小程序进阶实战:从 UI 组件库到全局状态管理全解DAY05
ui·微信小程序·小程序