简体   繁体   English

属性更改时,不会调用按钮命令CanExecute

[英]Button Command CanExecute not called when property changed

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. 当该文本框的值发生变化时,button命令不会调用它的命令的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: 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?

In your DelegateCommand implementation CanExecuteChanged should add/remove to CommandManager.RequerySuggested event 在您的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; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM