title: WPF MVVM RelayCommand multiple buttons on each DataGrid row, set enabled/disabled button state for selected row only
body: <p><strong>WPF</strong> </p>
  
  <p><strong>MVVM</strong></p>
  
  <p><strong>RelayCommands</strong></p>
  
  <p><strong>DataGrid with multiple buttons on each row.</strong></p>
  
  <p><strong>Goal:</strong> To enable and disable some of the buttons for the selected row only,  when I click on my "Start" button</p>
  
  <p><strong>Current Behavior:</strong> When I click the Start button, the buttons get enabled and disabled the same for all rows</p>
  
  <p>In this image you can see that I clicked on the Start button and the command fired and correctly set the enabled/disabled state of the other buttons however it applied it to all rows.</p>
  
  <p>I've been stuck trying to get it to apply for the selected item only.
  I'm currently trying to pass a parameter to the RelayCommand, if anyone could show me how to do that maybe it would work.</p>
  
  <p><a href="https://i.stack.imgur.com/Jr3Nf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Jr3Nf.png" alt="enter image description here"></a></p>
  
  <p><strong>XAML</strong></p>
  
  <pre><code>&lt;DataGrid x:Name="dataGridThreadView" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" 
                    IsReadOnly="True" CanUserResizeRows="False" CanUserReorderColumns="True" Margin="4"  
                    CanUserAddRows="False" CanUserDeleteRows="False" CanUserSortColumns="True" 
                    EnableRowVirtualization="True" ItemsSource="{Binding Threads}"
                    SelectedItem="{Binding Path=SelectedThread, Mode=TwoWay}"&gt;
  
              &lt;DataGrid.Columns&gt;
                  &lt;DataGridTextColumn Header="Name"
                          Binding="{Binding Thread.Name}"/&gt;
                  &lt;DataGridTemplateColumn Header="Actions"&gt;
                      &lt;DataGridTemplateColumn.CellTemplate&gt;
                          &lt;DataTemplate&gt;
                              &lt;StackPanel Orientation="Horizontal" Margin="2"&gt;
                                  &lt;Button Name="buttonStartThread" Content="Start" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.StartCommand}" CommandParameter="{Binding SelectedThread}"/&gt;
                                  &lt;Button Name="buttonSuspendThread" Content="Suspend" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.SuspendCommand}"/&gt;
                                  &lt;Button Name="buttonResumeThread" Content="Resume" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.ResumeCommand}"/&gt;
                                  &lt;Button Name="buttonInterruptThread" Content="Interrupt" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.InterruptCommand}"/&gt;
                                  &lt;Button Name="buttonAbortThread" Content="Abort" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.AbortCommand}"/&gt;
                              &lt;/StackPanel&gt;
                          &lt;/DataTemplate&gt;
                      &lt;/DataGridTemplateColumn.CellTemplate&gt;
                  &lt;/DataGridTemplateColumn&gt;
              &lt;/DataGrid.Columns&gt;
          &lt;/DataGrid&gt;
  </code></pre>
  
  <p><strong>ViewModel</strong></p>
  
  <pre><code> public class ThreadViewModel : PropertyChangedBase
  {
      public ThreadModel SelectedThread { get; set; }
      public ObservableCollection&lt;ThreadModel&gt; Threads { get; set; }
      private bool _disableStartButton = false;
      private bool _disableSuspendButton = false;
      private bool _disableResumeButton = false;
      private bool _disableInterruptButton = false;
      private bool _disableAbortButton = false;
  
      public RelayCommand StartCommand { get; private set; } // should only be set once in vm during construction
  
      public ThreadViewModel()
      {
          _disableStartButton = false;
          _disableSuspendButton = true;
          _disableResumeButton = true;
          _disableInterruptButton = true;
          _disableAbortButton = true;
          Threads = new ObservableCollection&lt;ThreadModel&gt;();
  
          StartCommand = new RelayCommand(OnStart, CanStart);
      }
  
      private void OnStart(object template)
      {
          this._disableStartButton = true;
          StartCommand.RaiseCanExecuteChanged();
          _disableSuspendButton = false;
          SuspendCommand.RaiseCanExecuteChanged();
          _disableInterruptButton = false;
          InterruptCommand.RaiseCanExecuteChanged();
          _disableAbortButton = false;
          AbortCommand.RaiseCanExecuteChanged();
      }
  
      private bool CanStart()
      {
          return !this._disableStartButton;
      }
  }
  </code></pre>
  
  <p><strong>RelayCommand class</strong></p>
  
  <pre><code>using System;
  using System.Windows.Input;
  
  namespace Multthreading
  {
  public class RelayCommand : ICommand
  {
      Action _TargetExecuteMethod;
      Func&lt;bool&gt; _TargetCanExecuteMethod;
  
      public RelayCommand(Action executeMethod)
      {
          _TargetExecuteMethod = executeMethod;
      }
  
      public RelayCommand(Action executeMethod, Func&lt;bool&gt; canExecuteMethod)
      {
          _TargetExecuteMethod = executeMethod;
          _TargetCanExecuteMethod = canExecuteMethod;
      }
  
      public void RaiseCanExecuteChanged()
      {
          CanExecuteChanged(this, EventArgs.Empty);
      }
      #region ICommand Members
  
      bool ICommand.CanExecute(object parameter)
      {
          if (_TargetCanExecuteMethod != null)
          {
              return _TargetCanExecuteMethod();
          }
          if (_TargetExecuteMethod != null)
          {
              return true;
          }
          return false;
      }
  
      // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
      // Prism commands solve this in their implementation
      public event EventHandler CanExecuteChanged = delegate { };
  
      void ICommand.Execute(object parameter)
      {
          if (_TargetExecuteMethod != null)
          {
              _TargetExecuteMethod();
          }
      }
      #endregion
  }
  
  public class RelayCommand&lt;T&gt; : ICommand
  {
      Action&lt;T&gt; _TargetExecuteMethod;
      Func&lt;T, bool&gt; _TargetCanExecuteMethod;
  
      public RelayCommand(Action&lt;T&gt; executeMethod)
      {
          _TargetExecuteMethod = executeMethod;
      }
  
      public RelayCommand(Action&lt;T&gt; executeMethod, Func&lt;T,bool&gt; canExecuteMethod)
      {
          _TargetExecuteMethod = executeMethod;
          _TargetCanExecuteMethod = canExecuteMethod;
      }
  
      public void RaiseCanExecuteChanged() 
      {
           CanExecuteChanged(this, EventArgs.Empty); 
      }
      #region ICommand Members
  
      bool ICommand.CanExecute(object parameter)
      {
          if (_TargetCanExecuteMethod != null)
          {
              T tparm = (T)parameter;
              return _TargetCanExecuteMethod(tparm);
          }
          if (_TargetExecuteMethod != null)
          {
              return true;
          }
          return false;
      }
  
      // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
      // Prism commands solve this in their implementation
      public event EventHandler CanExecuteChanged = delegate { };
  
      void ICommand.Execute(object parameter)
      {
          if (_TargetExecuteMethod != null)
          {
              _TargetExecuteMethod((T)parameter);
          }
      }
      #endregion
      }
  }
  </code></pre>