You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C# .NET6 WPF中实现ICommand.CanExecuteChanged事件的add方法?

WPF中ICommand接口CanExecuteChanged事件实现问题

我正在跟着视频学习为Exit菜单项创建Window.InputBinding,目前的尝试中不清楚如何实现ICommand.CanExecuteChanged事件,疑惑这是不是.NET6 WPF中ICommand接口的新要求?

以下是我的C# MainWindow.cs代码:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApp2
{
    public class ExitKey : ICommand
    {
        private MainWindow mw;

        public ExitKey(MainWindow mw0) { mw = mw0;}

        event EventHandler ICommand.CanExecuteChanged {
            add {
                //How to Implment this???
                throw new NotImplementedException();
            }

            remove {
                throw new NotImplementedException();
            }
        }

        bool ICommand.CanExecute(object parameter) {
            return true;
        }

        void ICommand.Execute(object parameter) {
              mw.menu1_file_exit.RaiseEvent(new 
              RoutedEventArgs(MenuItem.ClickEvent));
        }
    }

    public class KeyContext
    {
        private MainWindow mw;

        public KeyContext(MainWindow mw0) { mw = mw0; }

        // {Binding MyExitCommand}
        public ICommand MyExitCommand
        {
            get { return new ExitKey(mw); }
        }

    } //Class

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new KeyContext(this);            
        }

        private void menu1_file_exit_Click(
          object sender, RoutedEventArgs e)
        {
            MessageBox.Show("EXIT!");
        }
    } //Class

} //Namespace        

对应的XAML代码:

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Garbo" Height="900" Width="900" MinHeight="240" MinWidth="320">
    <Window.InputBindings>
        <KeyBinding Key="F5"
                    Command="{Binding MyExitCommand}"
        />
    </Window.InputBindings>

    <DockPanel>
        <Menu Name="menu1" DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem 
                    Name="menu1_file_exit"       
                    Header="E_xit" 
                    Command="{Binding ExitCommand}" 
                    InputGestureText="F5"  
                    Click="menu1_file_exit_Click"/>
            </MenuItem>
        </Menu>
    </DockPanel>
</Window>

问题解答

  1. CanExecuteChanged并非.NET6新特性:ICommand接口自WPF推出以来就包含该事件,它的作用是通知绑定目标(如MenuItem、KeyBinding)命令的可执行状态已变更,以便UI更新启用/禁用状态。

  2. 两种可行的实现方式:

    • 绑定CommandManager事件(推荐):
      WPF的CommandManager.RequerySuggested事件会在UI交互场景(如焦点切换、控件状态变化)自动触发重查询,无需手动维护触发逻辑:
      event EventHandler ICommand.CanExecuteChanged
      {
          add { CommandManager.RequerySuggested += value; }
          remove { CommandManager.RequerySuggested -= value; }
      }
      
    • 手动维护事件委托:
      若需精准控制触发时机,可自行维护事件字段,在可执行状态变化时手动调用触发方法:
      private event EventHandler _internalCanExecuteChanged;
      event EventHandler ICommand.CanExecuteChanged
      {
          add { _internalCanExecuteChanged += value; }
          remove { _internalCanExecuteChanged -= value; }
      }
      
      // 状态变化时调用此方法通知UI
      private void RaiseCanExecuteChanged()
      {
          _internalCanExecuteChanged?.Invoke(this, EventArgs.Empty);
      }
      
  3. 额外优化点:

    • XAML中MenuItem的Command="{Binding ExitCommand}"与ViewModel中的MyExitCommand名称不匹配,需统一名称才能正常绑定;
    • 避免在Command中直接操作View元素(如触发菜单Click事件),建议直接在Execute方法中实现退出逻辑,比如mw.Close();,遵循MVVM的解耦原则。

内容的提问来源于stack exchange,提问作者Bill Moore

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 02:45:33