Button CanExecute command not called when property is changed

I have a form with a text box and a button.

When this text field has changed value, the button command does not call the CanExecute method for this command.

The command parameter is set, but does not seem to change. After loading 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 that binding works because I created a behavior that gets the binding to the target and raises CanExecute when the binding changes.

With this behavior, CanExecute is invoked normally.

 <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:

 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 does not call CanExecute?

+5
source share
1 answer

In your implementation of the DelegateCommand CanExecuteChanged , you should add / remove to the CommandManager.RequerySuggested event

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

change it to

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

Source: https://habr.com/ru/post/1212701/


All Articles