title: How to Attach Command to Event in WPF Using MVVM - DataGrid Selection Changed to Update the RowCount Displayed in a TextBlock
body: <p>In order to attempt to get around the problem I outline in <a href="https://stackoverflow.com/q/17537276/626442">Binding Selected RowCount to TextBlock not Firing OnPropertyChanged after DataGrid Scroll</a>; namely updating a <code>TextBlock</code> with the currently selected row count of a <code>DataGrid</code> when it scrolls. I have attempted to introduce the <code>AttachedCommandBehaviour</code> designed by Marlon Grech [an amazing class structure that allows you to bind commands to specific events of a given control].</p>
  
  <p>Now for the question, using this <code>AttachedCommandBehaviour</code>, how can I get a <code>TextBlock</code> to update based upon a <code>DataGrid</code>'s <code>SelectionChangedProperty</code>?</p>
  
  <p>The XMAL is </p>
  
  <pre><code>&lt;Window x:Class="ResourceStudio.Views.AddCultureWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels" 
          xmlns:converters="clr-namespace:ResourceStudio.Converters" 
          xmlns:dataAccess="clr-namespace:ResourceStudio.DataAccess" 
          xmlns:attachedCommand="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
          Title="Add Culture" 
          Height="510" Width="400" 
          WindowStartupLocation="CenterOwner" 
          VerticalContentAlignment="Stretch" 
          MinWidth="380" MinHeight="295"&gt;
     &lt;DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch"&gt;
        &lt;Grid&gt;
           &lt;Grid.RowDefinitions&gt;
              &lt;RowDefinition Height="*"/&gt;
              &lt;RowDefinition Height="24"/&gt;
           &lt;/Grid.RowDefinitions&gt;
  
           &lt;Grid&gt;
              &lt;Grid.ColumnDefinitions&gt;
                 &lt;ColumnDefinition Width="15*"/&gt;
                 &lt;ColumnDefinition Width="377*"/&gt;
                 &lt;ColumnDefinition Width="15*"/&gt;
              &lt;/Grid.ColumnDefinitions&gt;
              &lt;Grid Grid.Column="1"&gt;
                 &lt;Grid&gt;
                    &lt;Grid.Resources&gt;
                       &lt;converters:EnumToBooleanConverter x:Key="enumToBooleanConverter"/&gt;
                       &lt;Style x:Key="HyperlinkButton" TargetType="Button"&gt;
                          &lt;Setter Property="Template"&gt;
                             &lt;Setter.Value&gt;
                                &lt;ControlTemplate TargetType="Button"&gt;
                                   &lt;ContentPresenter/&gt;
                                &lt;/ControlTemplate&gt;
                             &lt;/Setter.Value&gt;
                          &lt;/Setter&gt;
                       &lt;/Style&gt;
                    &lt;/Grid.Resources&gt;
                    &lt;Grid.RowDefinitions&gt;
                       &lt;RowDefinition Height="Auto"/&gt;
                       &lt;RowDefinition Height="1*"/&gt;
                       &lt;RowDefinition Height="Auto"/&gt;
                       &lt;RowDefinition Height="Auto"/&gt;
                       &lt;RowDefinition Height="Auto"/&gt;
                    &lt;/Grid.RowDefinitions&gt;
                    &lt;GroupBox Header="Filters" Grid.Row="0" Margin="0,0,0,5"&gt;
                       &lt;StackPanel VerticalAlignment="Top"&gt;
                          &lt;StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="2,2,2,2"&gt;
                             &lt;RadioButton Content="All Cultures" Margin="10,5,10,5" 
                                          HorizontalAlignment="Left" 
                                          IsChecked="{Binding SelectedFilterType, 
                                                      Converter={StaticResource enumToBooleanConverter}, 
                                                      ConverterParameter=AllCultures}"/&gt;
                             &lt;RadioButton Content="Neutral Cultures" Margin="10,5,10,5" 
                                          HorizontalAlignment="Left" 
                                          IsChecked="{Binding SelectedFilterType, 
                                                      Converter={StaticResource enumToBooleanConverter}, 
                                                      ConverterParameter=NeutralCultures}"/&gt;
                             &lt;RadioButton Content="Specific Cultures" Margin="10,5,10,5" 
                                          HorizontalAlignment="Left" 
                                          IsChecked="{Binding SelectedFilterType, 
                                                      Converter={StaticResource enumToBooleanConverter}, 
                                                      ConverterParameter=SpecificCultures}"/&gt;
                          &lt;/StackPanel&gt;
                          &lt;Grid&gt;
                             &lt;Grid.ColumnDefinitions&gt;
                                &lt;ColumnDefinition Width="Auto"/&gt;
                                &lt;ColumnDefinition Width="*"/&gt;
                             &lt;/Grid.ColumnDefinitions&gt;
                             &lt;Label Content="Language:" Grid.Column="0"/&gt;
                             &lt;TextBox HorizontalAlignment="Stretch" Grid.Column="1" 
                                      Margin="2,0,2,0" Height="22"/&gt;
                          &lt;/Grid&gt;
                       &lt;/StackPanel&gt;
                    &lt;/GroupBox&gt;
                    &lt;DataGrid x:Name="cultureDataGrid" Grid.Row="1" AlternatingRowBackground="Gainsboro" AlternationCount="2" 
                              HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
                              AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"
                              CanUserAddRows="False" CanUserDeleteRows="False" SelectionMode="Extended" 
                              EnableRowVirtualization="True" EnableColumnVirtualization="True" 
                              ItemsSource="{Binding Cultures, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, IsAsync=True}"&gt;
                       &lt;DataGrid.Columns&gt;
                          &lt;DataGridTextColumn Header="Code" Binding="{Binding Code}" IsReadOnly="True"/&gt;
                          &lt;DataGridTextColumn Header="Language" Binding="{Binding Language}" IsReadOnly="True"/&gt;
                          &lt;DataGridTextColumn Header="LocalName" Binding="{Binding LocalName}" IsReadOnly="True"/&gt;
                       &lt;/DataGrid.Columns&gt;
  
                       &lt;DataGrid.CellStyle&gt;
                          &lt;Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}"&gt;
                             &lt;Style.Triggers&gt;
                                &lt;Trigger Property="IsSelected" Value="True"&gt;
                                   &lt;Setter Property="Background" Value="#FF007ACC"/&gt;
                                   &lt;Setter Property="Foreground" Value="White"/&gt;
                                &lt;/Trigger&gt;
                             &lt;/Style.Triggers&gt;
                          &lt;/Style&gt;
                       &lt;/DataGrid.CellStyle&gt;
                       &lt;DataGrid.RowStyle&gt;
                          &lt;Style TargetType="DataGridRow"&gt;
                             &lt;Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, IsAsync=True}" /&gt;
                          &lt;/Style&gt;
                       &lt;/DataGrid.RowStyle&gt;
                    &lt;/DataGrid&gt;
                    &lt;StackPanel Grid.Row="2" HorizontalAlignment="Right"&gt;
                       &lt;Button Name="button1" Style="{StaticResource HyperlinkButton}" 
                               Focusable="False"&gt;
                          &lt;TextBlock&gt;
                              &lt;Hyperlink Focusable="False"&gt;
                                  Select All
                              &lt;/Hyperlink&gt;
                          &lt;/TextBlock&gt;
                       &lt;/Button&gt;
                    &lt;/StackPanel&gt;
                    &lt;GroupBox Grid.Row="3" Header="Options"&gt;
                       &lt;CheckBox Content="Copy default values" Margin="3,3"/&gt;
                    &lt;/GroupBox&gt;
                    &lt;StackPanel Grid.Row="4" Orientation="Horizontal" 
                                HorizontalAlignment="Right" Margin="0,2,0,2"&gt;
                       &lt;Button Content="Select" Width="70" Height="25" 
                               Margin="0,5,5,5" HorizontalAlignment="Right" 
                               VerticalContentAlignment="Center" IsDefault="True"/&gt;
                       &lt;Button Content="Cancel" Width="70" Height="25" 
                               Margin="5,5,0,5" HorizontalAlignment="Right" 
                               VerticalContentAlignment="Center" IsCancel="True"/&gt;
                    &lt;/StackPanel&gt;
                 &lt;/Grid&gt;
              &lt;/Grid&gt;
           &lt;/Grid&gt;
  
           &lt;StatusBar Grid.Row="1" Margin="0,0.4,0.4,-0.4"&gt;
              &lt;StatusBarItem DockPanel.Dock="Left" Background="#FF007ACC" Margin="0,2,0,0"&gt;
                 &lt;TextBlock Text="{Binding TotalSelectedCultures}"  Margin="5,0,0,0" Foreground="White"/&gt;
              &lt;/StatusBarItem&gt;
           &lt;/StatusBar&gt;
        &lt;/Grid&gt;
     &lt;/DockPanel&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>My ViewModel is </p>
  
  <pre><code>public class CultureDataViewModel : ViewModelBase
  {
      public FilterType SelectedFilterType { get; private set; }
      public ICollectionView CulturesView { get; private set; }
      public MultiSelectCollectionView&lt;CultureViewModel&gt; Cultures { get; private set; }
  
      public CultureDataViewModel()
      {
          SelectedFilterType = FilterType.AllCultures;
          LoadCultures();
      }
  
      void OnCultureViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          string IsSelected = "IsSelected";
          (sender as CultureViewModel).VerifyPropertyName(IsSelected);
          if (e.PropertyName == IsSelected)
              this.OnPropertyChanged("TotalSelectedCultures");
      }
  
      void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
      {
          if (e.NewItems != null &amp;&amp; e.NewItems.Count != 0)
              foreach (CultureViewModel cultVm in e.NewItems)
                  cultVm.PropertyChanged += this.OnCultureViewModelPropertyChanged;
  
          if (e.OldItems != null &amp;&amp; e.OldItems.Count != 0)
              foreach (CultureViewModel cultVm in e.OldItems)
                  cultVm.PropertyChanged -= this.OnCultureViewModelPropertyChanged;
      }
  
      public void LoadCultures()
      {
          // Fill the Culutres collection...
      }
  
      public string TotalSelectedCultures
      {
          get
          {
              int selectedCultures = this.Cultures.SelectedItems.Count;
              return String.Format("{0:n0} of {1:n0} cultures selected",
                                          selectedCultures,
                                          Cultures.Count);
          }
      }
  }
  </code></pre>
  
  <p>The link to a downloadable example of the use of the <code>AttachedCommandBehaviour</code> is <a href="https://skydrive.live.com/?cid=96f8d49aa44c79c1&amp;id=96F8D49AA44C79C1%21233" rel="nofollow noreferrer">Here</a>. Your help is most appreciated...</p>