2015-02-05 21 views
5

Mam formularz z polem tekstowym i przyciskiem.Polecenie przycisku CanExecute nie jest wywoływane po zmianie właściwości

Gdy ten pole tekstowe ma zmienioną wartość, polecenie przycisku nie wywołuje metody CanExecute tego polecenia.

Parametr polecenia jest ustawiony, ale nie wydaje się zmieniać. Po załadowaniu okna przycisk pozostaje wyłączony.

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

wiem wiązanie pracuje, bo stworzył zachowań, które odbiera wiążący cel i podnieść CanExecute gdy obowiązujące zmiany.

Przy takim zachowaniu CanExecute jest wywoływana normalnie.

<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(); 
    } 
} 

Czy ktoś wie dlaczego przycisk nie wywołać CanExecute?

+0

Jak Przycisk Polecenie zadziała po zmianie tekstu Pole tekstowe? –

+0

Ponieważ pole tekstowe jest powiązane z właściwością z powiadomieniem, a parametr CommandParameter przycisku jest powiązany z tą samą właściwością, zostanie powiadomiony i wywołany przez CanExecute metody Command Command –

Odpowiedz

8

W implementacji DelegateCommandCanExecuteChanged należy dodać/usunąć do CommandManager.RequerySuggested imprezy

występuje, gdy poleceń CommandManager wykryje warunki, które mogłyby zmienić zdolność polecenia do wykonania.

zmienić na

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

Potrzebuję publicznej metody podniesienia CanExecuteChanged. Czy mogę również dodać/usunąć do prywatnego _canExecuteChanged? A może jest lepszy sposób? –

+1

Technicznie możesz, ale jeśli chcesz ponownie zatwierdzić komendę, możesz wywołać ['CommandManager.InvalidateRequerySuggested'] (https://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.invalidaterequerysuggested (v = vs.110) .aspx). Zmusza on menedżera poleceń CommandManager do podniesienia zdarzenia RequerySuggested_. – dkozl

+0

Czy polecenie CommandManager.InvalidateRequerySuggested odświeża wszystkie polecenia aplikacji? –