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?