2017-03-04 35 views
2

MVVMへのパスを続けて、私はボタンコマンドに来た。かなりの試行錯誤の末、私はついにICommandを使ってButton_Clickコマンドの実際の例を得ました。どのボタンをクリックしたのかを確認する方法は? (MVVM)

私の問題は、ジェネリックイベントが作成されたため、ロジックを適用するためにどのボタンがクリックされたのかわかりません。私の例では、Senderの情報を入手できる場所は何も使用していません。通常RoutedEventArgsを使用して、以下のようなもの:

Button button = (Button)sender; 

は、これは私がこれまで持っているものです。

ICommandクラス:

public class CommandHandler : ICommand 
{ 
    private Action _action; 
    private bool _canExecute; 
    public CommandHandler(Action action, bool canExecute) 
    { 
     _action = action; 
     _canExecute = canExecute; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _canExecute; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     _action(); 
    } 
} 

とアクションにするコード:

private ICommand _clickCommand; 
public ICommand ClickCommand => _clickCommand ?? (_clickCommand = new CommandHandler(MyAction, _canExecute)); 

public ViewModelBase() 
{ 
    _canExecute = true;    
} 

public void MyAction() 
{ 
    //Apply logic here to differentiate each button 
} 

とXAMLを、

<Button Command="{Binding ClickCommand}" Style="{StaticResource RedButtonStyle}">MyButton</Button> 

は、どのように私はボタンがあるかを識別するに行きますか他のボタンと同じコマンドをバインドするときにクリックされますか?

+1

ちょっと興味がありますが、なぜ* 2 * ICommandsを使用しないのですか? –

+1

@ XanderLuciano、私はちょうどいくつかの基準を適用すると思った方法でボタンをdiffirenitateそれを行う方法でした。乾杯! – KyloRen

+1

フェア十分!私はちょうど約1ヶ月前にもMVVMを使い始めたので、あなたの思考を調整しなければならないという苦労を理解しています。がんばろう! –

答えて

1

あなたはおそらくは、しかし、あなたはCommandParameter=""

はあなたちょうどかかわらず、2 ICommandsを使用する必要があります使用することができるべきではありません。

XAML:

<Button Command="{Binding ClickCommandEvent}" CommandParameter="Jack"/>

のViewModel:

public RelayCommand ClickCommandEvent { get; set; } 

public SomeClass() 
{ 
    ClickCommandEvent = new RelayCommand(ClickExecute); 
} 

public void ClickExecute(object param) 
{ 
    System.Diagnostics.Debug.WriteLine($"Clicked: {param as string}"); 

    string name = param as string; 
    if (name == "Jack") 
     HighFive(); 
} 

とあなたのRelayCommandクラスが this boiler plate次のようになります。これはあなたのクリック Buttonを与える

public class RelayCommand : ICommand 
{ 
    #region Fields 
    readonly Action<object> _execute; 
    readonly Predicate<object> _canExecute; 

    #endregion 

    #region Constructors 
    public RelayCommand(Action<object> execute) : this(execute, null) { } 

    public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 

     _execute = execute; 
     _canExecute = canExecute; 
    } 
    #endregion 

    #region ICommand Members 
    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null ? true : _canExecute(parameter); 
    } 

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

    public void Execute(object parameter) 
    { 
     _execute(parameter); 
    } 
    #endregion 
} 
+1

答えをありがとう、学習のために私はこれを試してみるつもりですが、私はプロジェクトで別々のコマンドで行くつもりです。歓声 – KyloRen

+1

熱狂を愛する!あなたが何かトラブルに遭遇したら教えてください!あなたはMVVMを愛するでしょう。あなたは 'INotifyPropertyChanged'をまだやりましたか? –

+1

私はこのものが大好きです。はい、私は 'INotifyPropertyChanged'を実装しました。' DataGrid'とそのすべてのidosyncrosisで始まり、新しいレコードを追加、更新できますが、 'Context.Menu'でレコードを削除する方法はまだ分かりません。だから私は今のところそれを残してボタンコマンドを開始します。私が一番恐れているのは 'TreeView'とMVVMです。 – KyloRen

2

あなたは、すべてのボタンを同じコマンドにバインドするはずはありません。各ボタンごとに異なるコマンドを作成するだけです。あなたがしをしたい場合

+0

これは、MVVM以外のシナリオでは名前付きハンドラと似ていますが、この点でコードはビューから切り離されています。おかげで – KyloRen

2

<Button Command="{Binding ClickCommand}" 
     CommandParameter="{Binding RelativeSource={RelativeSource Self}}"/> 
+0

乾杯。 – KyloRen

関連する問題