views:

1106

answers:

2

Trying to figure out how to use EventToCommand to set a datagrid double click handler for rows. The command lives in the viewmodel for each row. Just that much out of my experience, since I haven't used interactions yet.

Thanks.

I would have used mvvmlight tag, but I don't have high enough rep yet to make new tags.

+2  A: 

This would be the solution if the Command lives on the "GridVieModel" and not on the "RowViewModel".

    <Window...    
         ...xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
            xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras">
         <dg:DataGrid x:Name="dg">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseDoubleClick">
                            <GalaSoft_MvvmLight_Command:EventToCommand CommandParameter="{Binding SelectedItem, ElementName=dg}" Command="{Binding Path=SelectCommand, Mode=OneWay}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
            </dg:DataGrid>
    </Window>

You could create a rowview since the row also has its own viewmodel and use the mousedoubleclick event of a child element of the row (container) in the rowview.

Or you create a converter for your command binding:

<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding SelectedItem, ElementName=dg, Mode=OneWay, Converter=...}"/>

The converter then would check if the selectedItem is of the required type to return the command (Something like ISelectCommandable with a RelayCommand Property)

CodeWeasel
Torn... I won't have the opportunity to try this out for a long time, but don't want to leave it unanswered. It looks right in theory, but I really wanted something where the command was on the RowViewModel.<dg:DataGrid x:Name="dg" Items="RowVMCollection">Or perhaps you're implying that DataGrid doesn't provide a double click that supports identifying the row involved?
Tom
The idea behind the converter was, that the converter casts the SelectedItem and returns the Command. That way you would have called the command on the RowViewModel (I am not really sure if you even need it or if you can do something like SelectedItem.SelectCommand )To identify if a row has been doubleclicked you would need the EventArgs. But you can return that to with the mvvm-light toolkit.
CodeWeasel
K, thanks for the sample syntax. I'll respond again if I ever get around to trying out this method.
Tom
+2  A: 

In case anyone comes looking here and wonders how I ended up doing it w/o EventToCommand

public class DataGridAttachedBehaviors
{
   #region DoubleClick

   public static DependencyProperty OnDoubleClickProperty = DependencyProperty.RegisterAttached(
       "OnDoubleClick",
       typeof(ICommand),
       typeof(DataGridAttachedBehaviors),
       new UIPropertyMetadata(DataGridAttachedBehaviors.OnDoubleClick));

   public static void SetOnDoubleClick(DependencyObject target, ICommand value)
   {
      target.SetValue(DataGridAttachedBehaviors.OnDoubleClickProperty, value);
   }

   private static void OnDoubleClick(DependencyObject target, DependencyPropertyChangedEventArgs e)
   {
      var element = target as Control;
      if (element == null)
      {
         throw new InvalidOperationException("This behavior can be attached to a Control item only.");
      }

      if ((e.NewValue != null) && (e.OldValue == null))
      {
         element.MouseDoubleClick += MouseDoubleClick;
      }
      else if ((e.NewValue == null) && (e.OldValue != null))
      {
         element.MouseDoubleClick -= MouseDoubleClick;
      }
   }

   private static void MouseDoubleClick(object sender, MouseButtonEventArgs e)
   {
      UIElement element = (UIElement)sender;
      ICommand command = (ICommand)element.GetValue(DataGridAttachedBehaviors.OnDoubleClickProperty);
      command.Execute(null);
   }

   #endregion DoubleClick

  #region SelectionChanged
  //removed
  #endregion
}

In my xaml:

<dg:DataGrid.RowStyle>
   <Style BasedOn="{StaticResource DataGridDemoRowStyle}"           
          TargetType="{x:Type dg:DataGridRow}">
       <Setter Property="skins:DataGridAttachedBehaviors.OnDoubleClick"
               Value="{Binding Recall}" />
   </Style>
</dg:DataGrid.RowStyle>
Tom