wpf CanExecuteChanged和CommandManager.QuerySuggested的实际任务是什么?

wmomyfyw  于 2023-03-04  发布在  其他
关注(0)|答案(3)|浏览(133)

我从Josh Smith的MVVM tutorial中获得了以下代码。
有谁能快速解释一下这段代码实际上是做什么的?

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }     
}

我不明白两件事:

  1. CanExecuteChanged事件的作用是什么?
  2. CommandManager.RequerySuggested的功能是什么?
    上面的代码来自RelayCommand类。
g2ieeal7

g2ieeal71#

  1. CanExecuteChanged通知绑定到该ICommand的任何命令源(如ButtonMenuItem),CanExecute返回的值已更改。命令源关心这一点,因为它们通常需要相应地更新其状态(例如,如果CanExecute()返回false,则Button将禁用自身)。
    1.每当CommandManager认为某些更改会影响命令的执行能力时,就会引发CommandManager.RequerySuggested事件。例如,这可能是焦点的更改。事实证明,此事件经常引发。
    所以,从本质上讲,这段代码所做的是确保每当命令管理器认为命令的执行能力发生了变化,即使它实际上没有发生变化,命令也会引发CanExecuteChanged
    实际上我不喜欢这种实现ICommand.CanExecuteChanged的方法--感觉很懒,而且不完全可靠。我更喜欢更细粒度的方法,其中命令公开一个方法(例如RaiseCanExecuteChanged()),您可以调用该方法来引发CanExecuteChanged,然后在适当的时间从视图模型中调用该方法。
    例如,如果您有一个删除当前选定客户的命令,则该命令将具有一个CanExecute()处理程序,该处理程序仅在选定客户时返回true。因此,只要选定客户发生更改,您就将调用RaiseCanExecuteChanged
fdx2calv

fdx2calv2#

  • RoutedCommands可以自动通知它们的CanExecute是否发生了更改,因为我们在这里实现的是ICommand,而WPF系统并不知道,所以我们将它们与CommandManager的RequerySuggested事件关联起来。
  • 现在,当焦点改变、编辑任何控件等时,WPF系统会经常调用此事件。因此,依次引发CanExecuteChanged。当您的按钮侦听此事件时,它将重新调用CanExecute以了解最新状态。

这里有一个可能会感兴趣的article

9fkzdhlc

9fkzdhlc3#

实现RaiseCanExecuteChanged()函数
命令类:

public class CommandBase : ICommand
{
    Action _TargetExecuteMethod;
    Func<bool> _TargetCanExecuteMethod;

    public CommandBase(Action executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public CommandBase(Action executeMethod, Func<bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }

    public event EventHandler CanExecuteChanged

    public bool CanExecute(object parameter)
    {             

        if (_TargetCanExecuteMethod != null)
        {
            return _TargetCanExecuteMethod();
        }

        if (_TargetExecuteMethod != null)
        {
            return true;
        }                       
                    
        return false;
    }

    public void Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod();
        }
    }
}

查看:

<TextBox Grid.Row="3" Text="{Binding TextValue, UpdateSourceTrigger=PropertyChanged }"/>
<Button Content="DoSomething" Command="{Binding DoSomething}" />

视图模型类:

public class MyclassViewModel
{
     private string textValue;

     public String TextValue
     {
        get {                
            return textValue; 
        }
        set {               
            textValue = value;
            DoSomething.RaiseCanExecuteChanged();
        }
     }

     public CommandBase DoSomething { get; set; }

     public MyclassViewModel() //Constructor
     {            
        DoSomething = new CommandBase(OnDoSomething, CanDoSomething);            
     }

     private bool CanDoSomething()
     {
        if (TextValue?.Length > 5)
        {
            return true;
        }
        return false;
     }

    private void OnDoSomething()
    {
        //Do Something
    }
}

相关问题