2015-05-02 5 views
5

Prima di dire sono all'inizio di WPF e MVVM Pattern.Come utilizzare il metodo CanExecute da ICommand su WPF

Durante il tentativo di alcuni comandi personalizzati mi chiedevo come utilizzare il metodo CanExecute dall'interfaccia ICommand.

Nel mio esempio ho un SaveCommand che ho solo quello che deve essere abilitato quando l'oggetto è salvabile. Il codice XAML del mio Savebutton assomiglia a questo:

<Button Content="Save" Command="{Binding SaveCommand, Mode=TwoWay}" /> 

Questo è il codice della mia classe salvare:

class Save : ICommand 
{ 
    public MainWindowViewModel viewModel { get; set; } 

    public Save(MainWindowViewModel viewModel) 
    { 
     this.viewModel = viewModel; 
    } 

    public bool CanExecute(object parameter) 
    { 

     if (viewModel.IsSaveable == false) 
      return false; 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     viewModel.Save(); 
    } 
} 

La proprietà salvare nel ViewModel assomiglia a questo:

public ICommand SaveCommand 
    { 
     get 
     { 
      saveCommand = new Save(this); 
      return saveCommand; 
     } 
     set 
     { 
      saveCommand = value; 
     } 
    } 

Questo costrutto non ha funzionato. Il pulsante non abilita se stesso quando isSaveable è true.

risposta

4

Invece di definire la propria implementazione di ICommand, utilizzare RelayCommand.

Nel seguente codice di esempio, il salvataggio Button è abilitato quando l'utente digita qualcosa nello TextBox.

XAML:

<Window x:Class="RelayCommandDemo.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <StackPanel HorizontalAlignment="Center"> 
     <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Margin="5" Width="120"/> 
     <Button Content="Save" Command="{Binding SaveCommand}" Margin="3"/> 
    </StackPanel> 
</Window> 

codice dietro:

using System; 
using System.Windows; 
using System.Windows.Input; 

namespace RelayCommandDemo 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      DataContext = new VM(); 
     } 
    } 
    public class VM 
    { 
     public String Name { get; set; } 

     private ICommand _SaveCommand; 

     public ICommand SaveCommand 
     { 
      get { return _SaveCommand; } 
     } 

     public VM() 
     { 
      _SaveCommand = new RelayCommand(SaveCommand_Execute, SaveCommand_CanExecute); 
     } 

     public void SaveCommand_Execute() 
     { 
      MessageBox.Show("Save Called"); 
     } 

     public bool SaveCommand_CanExecute() 
     { 
      if (string.IsNullOrEmpty(Name)) 
       return false; 
      else 
       return true; 
     } 
    } 

    public class RelayCommand : ICommand 
    { 
     public event EventHandler CanExecuteChanged 
     { 
      add { CommandManager.RequerySuggested += value; } 
      remove { CommandManager.RequerySuggested -= value; } 
     } 
     private Action methodToExecute; 
     private Func<bool> canExecuteEvaluator; 
     public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator) 
     { 
      this.methodToExecute = methodToExecute; 
      this.canExecuteEvaluator = canExecuteEvaluator; 
     } 
     public RelayCommand(Action methodToExecute) 
      : this(methodToExecute, null) 
     { 
     } 
     public bool CanExecute(object parameter) 
     { 
      if (this.canExecuteEvaluator == null) 
      { 
       return true; 
      } 
      else 
      { 
       bool result = this.canExecuteEvaluator.Invoke(); 
       return result; 
      } 
     } 
     public void Execute(object parameter) 
     { 
      this.methodToExecute.Invoke(); 
     } 
    } 
}