2017-03-04 75 views
2

繼續沿着MVVM的路徑,我來到了按鈕命令。經過相當多的試驗和錯誤,我終於有了一個使用ICommandButton_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

夠公平的!我剛剛在一個月前開始使用MVVM,所以我明白需要調整思路的努力。祝你好運! –

回答

1

可能不應該,但如果你想,您可以使用CommandParameter=""

應該只使用2個ICommand雖然。

XAML:

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

視圖模型:

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

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,你一定會喜歡MVVM。你做了一個'INotifyPropertyChanged'嗎? –

+1

我喜歡這個東西。是的,我已經實現了'INotifyPropertyChanged',我開始使用'DataGrid'及其idosyncrosis,可以更新,添加新記錄等,但仍然無法弄清楚如何用'Context.Menu'刪除記錄。所以我現在就離開這個並開始使用按鈕命令。我最擔心的是'TreeView'和MVVM。 – KyloRen

2

您不應該將所有按鈕綁定到相同的命令。只需爲每個按鈕製作不同的命令。

+0

好的,我看到了,在這方面,它與非MVVM場景中的命名處理程序類似,但這種方式代碼與視圖分離。謝謝 – KyloRen

2

這會給你的點擊Button

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

紫外線可幫助您獲得有用的答案。乾杯。 – KyloRen