2016-11-14 3 views
0

私のWPF-Appのメインウィンドウには多くのボタンがあります。 これらのボタンのコマンドは同じインプリメンテーション/機能を持つ必要がありますが、どのボタンが押されたかによって、そのファンクションがアクセスするファイル/パスが変更されます。 ボタンクリックイベントハンドラ(Windowsフォーム)を使用せずにViewModelからクリックされたボタンを検出する方法はありますか?ここでViewModelからどのボタンがクリックされたかを検出するWPF

は、クラスRelayCommandの実装です:ここで

public class RelayCommand : ICommand 
{ 

    readonly Func<Boolean> _canExecute; 
    readonly Action _execute; 


    public RelayCommand(Action execute) 
     : this(execute, null) 
    { 
    } 

    public RelayCommand(Action execute, Func<Boolean> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 
     _execute = execute; 
     _canExecute = canExecute; 
    } 


    public event EventHandler CanExecuteChanged 
    { 
     add 
     { 

      if (_canExecute != null) 
       CommandManager.RequerySuggested += value; 
     } 

     remove 
     { 

      if (_canExecute != null) 
       CommandManager.RequerySuggested -= value; 
     } 
    } 


    public Boolean CanExecute(Object parameter) 
    { 
     return _canExecute == null ? true : _canExecute(); 
    } 

    public void Execute(Object parameter) 
    { 
     _execute(); 
    } 
} 

は、ビューモデルでは、コマンドのコードです:

void DoThisWorkExecute() 
    { 
     // if Button1 is clicked...do this 

     // if Button2 is clicked...do this 
    } 

    bool CanDoThisWorkExecute() 
    { 
     return true; 
    } 

    public ICommand ButtonCommand { get { return new RelayCommand(DoThisWorkExecute, CanDoThisWorkExecute); } } 
+0

がどのようにボタンをインスタンス化している参照してください?一般的なMVVMの方法は、CommandとCommandParameterの両方をXAMLにバインドし、パラメータを使用してパスを決定することです。 – PMV

+0

フィールド '_execute'と' _canExecute'の定義は、ちょっと疑わしいです(MVVM light?)。これは 'Action 'と 'Func 'でなければなりません。したがって、ICommandメソッドのパラメータを渡すことができます。 –

答えて

2

あなたはCommandParameterを使用することができます。そのような何か:このため

<Button Content="Open" Command="{Binding Path=ButtonCommand}" CommandParameter="Open"/> 
<Button Content="Save" Command="{Binding Path=ButtonCommand}" CommandParameter="Save"/> 

ます。ただしRelayCommand

/// <summary> 
/// https://gist.github.com/schuster-rainer/2648922 
/// Implementation from Josh Smith of the RelayCommand 
/// </summary> 
public class RelayCommand : ICommand 
{ 
    #region Fields 

    readonly Predicate<object> _canExecute; 
    readonly Action<object> _execute; 
    #endregion // Fields 

    #region Constructors 

    /// <summary> 
    /// Initializes a new instance of the <see cref="RelayCommand"/> class. 
    /// </summary> 
    /// <param name="execute">The execute.</param> 
    public RelayCommand(Action<object> execute) 
     : this(execute, null) 
    { 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="RelayCommand"/> class. 
    /// </summary> 
    /// <param name="execute">The execute.</param> 
    /// <param name="canExecute">The can execute.</param> 
    /// <exception cref="System.ArgumentNullException">execute</exception> 
    public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
    { 
     if (execute == null) 
      throw new ArgumentNullException("execute"); 

     _execute = execute; 
     _canExecute = canExecute; 
    } 
    #endregion // Constructors 

    #region ICommand Members 


    /// <summary> 
    /// Occurs when changes occur that affect whether or not the command should execute. 
    /// </summary> 
    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    /// <summary> 
    /// Defines the method that determines whether the command can execute in its current state. 
    /// </summary> 
    /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param> 
    /// <returns>true if this command can be executed; otherwise, false.</returns> 
    public bool CanExecute(object parameter) 
    { 
     return _canExecute == null ? true : _canExecute(parameter); 
    } 
    /// <summary> 
    /// Defines the method to be called when the command is invoked. 
    /// </summary> 
    /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param> 
    public void Execute(object parameter) 
    { 
     _execute(parameter); 
    } 

    #endregion // ICommand Members 
} 

のわずかに異なる実装が必要になります。代わりに、クリックされたボタンを尋ねる、私はそれぞれ個別のアクションのためのコマンドになるだろう(たとえば、オープン、セーブ、終了)。あなたのコマンド(コンテキストメニュー、KeyBindings、ツールバーなど)を再利用するときには、ずっとトラブルが少なくなります。常にui要素を指定する必要があります。これは実際にMVVMのパターンを破ります。 RelayCommandのフルパワーを利用するには、実際には古いwinformsの手法を取り除かなければなりません。

私はコードスニペットを書いたので、すべてのコードを書く必要はありません。

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
      <Title>RelayCommand</Title> 
      <Shortcut>RelayCommand</Shortcut> 
      <Description>Code snippet for usage of the Relay Command pattern</Description> 
      <Author>Mat</Author> 
      <SnippetTypes> 
       <SnippetType>Expansion</SnippetType> 
      </SnippetTypes> 
     </Header> 
     <Snippet> 
      <Declarations> 
       <Literal> 
        <ID>name</ID> 
        <ToolTip>Name of the command</ToolTip> 
        <Default>Save</Default> 
       </Literal> 
      </Declarations> 
      <Code Language="csharp"> 
       <![CDATA[ private RelayCommand _$name$Command; 
     public ICommand $name$Command 
     { 
      get 
      { 
       if (_$name$Command == null) 
       { 
        _$name$Command = new RelayCommand(param => this.$name$(param), 
         param => this.Can$name$(param)); 
       } 
       return _$name$Command; 
      } 
     } 

     private bool Can$name$(object param) 
     { 
      return true; 
     } 

     private void $name$(object param) 
     { 
      MessageServiceHelper.RegisterMessage(new NotImplementedException()); 
     }]]> 
      </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets> 

https://msdn.microsoft.com/en-us/library/z41h7fat.aspx

関連する問題