wpf 属性更改时未调用按钮命令 CanExecute

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28343632/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:54:49  来源:igfitidea点击:

Button Command CanExecute not called when property changed

c#wpfbindingicommand

提问by Thiago Romam

I have a form with a textbox and a button.

我有一个带有文本框和按钮的表单。

When that textbox has it's value changed, the button command doesn't call the CanExecute method of it's command.

当该文本框的值发生更改时,按钮命令不会调用其命令的 CanExecute 方法。

The command parameter is set but doesn't seem to change. After load the window, the button remains disabled.

命令参数已设置但似乎没有更改。加载窗口后,该按钮保持禁用状态。

<TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Save" Command="{Binding SaveChangesCommand}" CommandParameter="{Binding Name}" />

I know the binding is working because I created a behavior that receives a target binding and raise the CanExecute when the the binding changes.

我知道绑定正在工作,因为我创建了一个接收目标绑定并在绑定更改时引发 CanExecute 的行为。

With this behavior, the CanExecute is called normally.

有了这种行为,可以正常调用 CanExecute。

<Button Content="Save" Command="{Binding SaveChangesCommand}">
    <i:Interaction.Behaviors>
        <behaviors:CallCommandCanExecuteWhenBindingChange Target="{Binding Name}" />
    </i:Interaction.Behaviors>
</Button>

ViewModel:

视图模型:

public class EditViewModel : INotifyPropertyChanged
{
    private string _name;

    public EditViewModel()
    {
        SaveChangesCommand = new DelegateCommand(p => SaveChanges(), p => CanSaveChanges());
    }

    public string Name
    {
        get { return _name; }
        set
        {
            if (value == _name) return;
            _name = value;
            OnPropertyChanged();
        }
    }

    public DelegateCommand SaveChangesCommand { get; private set; }

    private void SaveChanges()
    {
    }
    private bool CanSaveChanges()
    {
        return !string.IsNullOrWhiteSpace(Name);
    }
}

DelegateCommand:

委托命令:

public interface IBaseCommand : ICommand
{
    void OnCanExecuteChanged();
}

public class DelegateCommand : IBaseCommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
        OnCanExecuteChanged();
    }

    public void OnCanExecuteChanged()
    {
        var handler = CanExecuteChanged;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }
}

CallCommandCanExecuteWhenBindingChange:

CallCommandCanExecuteWhenBindingChange:

public class CallCommandCanExecuteWhenBindingChange : Behavior<FrameworkElement>
{
    public static readonly DependencyProperty<CallCommandCanExecuteWhenBindingChange, object> TargetProperty;
    private ICommandBase _command;

    static CallCommandCanExecuteWhenBindingChange()
    {
        var dependency = new DependencyRegistry<CallCommandCanExecuteWhenBindingChange>();

        TargetProperty = dependency.Register(b => b.Target, s => s.OnTargetChange());
    }

    public object Target
    {
        get { return TargetProperty.Get(this); }
        set { TargetProperty.Set(this, value); }
    }

    private void OnTargetChange()
    {
        if (_command == null && AssociatedObject != null)
        {
            var field = AssociatedObject.GetType().GetProperty("Command");
            _command = (IBaseCommand)field.GetValue(AssociatedObject);
        }

        if (_command != null)
            _command.OnCanExecuteChanged();
    }
}

Does anyone know why the button doesn't call the CanExecute?

有谁知道为什么按钮不调用 CanExecute?

回答by dkozl

In your DelegateCommandimplementation CanExecuteChangedshould add/remove to CommandManager.RequerySuggestedevent

在您的DelegateCommand实现中CanExecuteChanged应该添加/删除CommandManager.RequerySuggested事件

Occurs when the CommandManager detects conditions that might change the ability of a command to execute.

当 CommandManager 检测到可能改变命令执行能力的条件时发生。

change it to

将其更改为

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