WPF ICommand命令、INotifyPropertyChanged通知更改

120

ICommand 是实现 命令模式 的核心接口,用于解耦用户界面操作(如按钮点击)和业务逻辑,常用于MVVM架构。

INotifyPropertyChanged 接口在 WPF 中用于实现数据绑定中的双向通知机制,确保数据模型的属性变更能自动反映到绑定的 UI 元素上。

ICommand 命令

作用

解耦UI和逻辑:允许将控件(如按钮)的交互行为(如点击)绑定到ViewModel中的方法,而非直接在代码后台处理。

控制操作的可用性:通过 CanExecute 动态控制命令是否可执行(如按钮的启用/禁用状态)。

事件通知:通过 CanExecuteChanged 事件通知UI更新命令的可用性状态。

实现步骤

1. 自定义命令类(如 LoginCommand)

实现 ICommand 接口,通过委托传递执行逻辑:

    /// <summary>
    /// 处理UI逻辑
    /// </summary>
    public class LoginCommand : ICommand
    {
        Action executeAction;
        public LoginCommand(Action action)
        {
            executeAction = action;
        }

        public event EventHandler? CanExecuteChanged;

        public bool CanExecute(object? parameter)
        {
            return true;
        }

        public void Execute(object? parameter)
        {
            executeAction();
        }
    }

2. 在ViewModel中定义命令

    /// <summary>
    /// 处理业务逻辑
    /// </summary>
    public class MainWindowViewModel : ViewModelBase
    {
        public string? userName;
        public string? UserName { get { return userName; } set { userName = value; OnPropertyChanged(); } }
        
        public string? password;
        public string? Password { get { return password; } set { password = value; OnPropertyChanged(); } }

        private string? message;
        public string? Message { get { return message; } set { message = value; OnPropertyChanged(); } }

        // 在ViewModel中定义命令
        public LoginCommand LoginCommand { get; set; }

        public MainWindowViewModel()
        {
            LoginCommand = new LoginCommand(Login);
        }

        public void Login()
        {
            MessageBox.Show("点击了登录");
            
            // TO DO: 登录逻辑
            // ...

            Message = "登录成功";
            UserName = "";
            Password = "";
        }
    }

3. XAML中绑定命令

<Window x:Class="WpfApp4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="186" Width="350">
    <Grid>
        <StackPanel Orientation="Vertical" Margin="20">
            <TextBox Text="{Binding UserName}" Margin="4"/>
            <TextBox Text="{Binding Password}" Margin="4"/>
            <!--绑定命令-->
            <Button Content="登录" Margin="4" Command="{Binding LoginCommand}"/>
            <TextBlock Text="{Binding Message}" Margin="4"/>
        </StackPanel>
    </Grid>
</Window>

INotifyPropertyChanged 通知更新

INotifyPropertyChanged 接口在 WPF 中用于实现数据绑定中的双向通知机制,确保数据模型的属性变更能自动反映到绑定的 UI 元素上。

核心作用

数据驱动UI更新:当数据模型(如 ViewModel 或实体类)的属性值发生变化时,通过触发 PropertyChanged 事件,通知 UI 更新显示,无需手动操作控件。

支持MVVM模式:在 MVVM 架构中,ViewModel 通过实现该接口,使视图(View)能自动响应数据变化,解耦业务逻辑与界面。

高效更新:仅通知实际发生变化的属性,避免全局刷新,提升性能。

实现方式

1.实现接口

数据模型类需继承 INotifyPropertyChanged,并定义 PropertyChanged 事件:

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

        public void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

2.属性触发事件

在属性的 setter 中检查值变化,并调用 OnPropertyChanged:

    /// <summary>
    /// 处理业务逻辑
    /// </summary>
    public class MainWindowViewModel : ViewModelBase
    {
        public string? userName;
        public string? UserName { get { return userName; } set { userName = value; OnPropertyChanged(); } }
        
        public string? password;
        public string? Password { get { return password; } set { password = value; OnPropertyChanged(); } }

        private string? message;
        public string? Message { get { return message; } set { message = value; OnPropertyChanged(); } }

        public LoginCommand LoginCommand { get; set; }

        public MainWindowViewModel()
        {
            LoginCommand = new LoginCommand(Login);
        }

        public void Login()
        {
            MessageBox.Show("点击了登录");
            
            // TO DO: 登录逻辑
            // ...

            Message = "登录成功";
            UserName = "";
            Password = "";
        }
    }