WPF命令与MVVM模式:打造优雅的应用程序架构

1. 🧩 命令系统基础

1.1 🤔 为什么需要命令?

在传统事件处理模型中,我们这样处理按钮点击:

private void Button_Click(object sender, RoutedEventArgs e)
{
   
    // 处理点击逻辑
}

这种模式存在几个问题:

  • 🚫 业务逻辑与UI代码混杂
  • 🔌 难以实现启用/禁用状态管理
  • 🔄 复用性差

命令系统解决了这些问题!

1.2 🏗️ ICommand接口

WPF命令系统基于ICommand接口:

public interface ICommand
{
   
    event EventHandler CanExecuteChanged;
    bool CanExecute(object parameter);
    void Execute(object parameter);
}

1.3 🛠️ 实现基本命令

创建一个简单的命令类:

/// <summary>
/// 实现ICommand接口的RelayCommand类,用于将UI操作(如按钮点击)绑定到ViewModel中的方法
/// </summary>
public class RelayCommand : ICommand
{
   
    // 私有字段,存储要执行的委托
    private readonly Action _execute;
    // 私有字段,存储判断命令是否可以执行的委托(可选)
    private readonly Func<bool> _canExecute;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="execute">要执行的委托方法</param>
    /// <param name="canExecute">判断命令是否可以执行的委托方法(可选)</param>
    /// <exception cref="ArgumentNullException">当execute参数为null时抛出</exception>
    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
   
        // 检查execute参数是否为null,如果是则抛出异常
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        // 可选地设置canExecute委托
        _canExecute = canExecute;
    }

    /// <summary>
    /// 当命令的可执行状态可能已更改时触发的事件
    /// </summary>
    public event EventHandler CanExecuteChanged;

    /// <summary>
    /// 确定此命令是否可以在其当前状态下执行
    /// </summary>
    /// <param name="parameter">命令使用的数据(此实现中未使用)</param>
    /// <returns>如果此命令可以执行,则为true;否则为false</returns>
    public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;

    /// <summary>
    /// 执行命令
    /// </summary>
    /// <param name="parameter">命令使用的数据(此实现中未使用)</param>
    public void Execute(object parameter) => _execute();

    /// <summary>
    /// 引发CanExecuteChanged事件,通知命令的可执行状态可能已更改
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
   
        // 使用空事件参数触发CanExecuteChanged事件
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

2. 🏛️ MVVM模式详解

2.1 🧱 MVVM三大组件

组件 职责 示例
🎨 ​​View ​​ 用户界面展示 MainWindow.xaml
📦 ​​ViewModel ​​ 业务逻辑和状态 MainViewModel.cs
🗃️ ​​Model​​ 数据模型和业务规则 Product.cs

2.2 🏗️ 创建ViewModel基类

public abstract class ViewModelBase : INotifyPropertyChanged
{
   
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
   
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
   
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

2.3 🎯 典型ViewModel示例

public class ProductViewModel : ViewModelBase
{
   
    private string _searchText;
    private ObservableCollection<Product> _products;
    
    public string SearchText
    {
   
        get => _searchText;
        set
        {
   
            if (SetField(ref _searchText, value))
            {
   
                SearchCommand.RaiseCanExecuteChanged();
            }
        }
    }
    
    public ObservableCollection<Prod
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hare_bai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值