Search code examples
c#wpfmvvmmouseeventicommand

WPF - Connect EventSetter to an ICommand


I'm looking for a solution where I double click on a DataGridRow that calls a method in my ViewModel with an ICommand.

I have this code for my DataGrid's DataGridRow style:

<DataGrid.Resources>
    <Style TargetType="{x:Type DataGridRow}">
        <EventSetter Event="MouseDoubleClick"
                     Handler="DataGridRow_MouseDoubleClick" />
    </Style>
</DataGrid.Resources>

This works, but...
I need to have the method DataGridRow_MouseDoubleClick in the XAML's code-behind. Then in that method I need to call the method in my ViewModel.
I would like to bypass the code-behind and directly call the method in the ViewModel with an ICommand.

I found this code which was elegant but, calls the method whereever I (left) double click on the DataGrid.

<DataGrid>
    <DataGrid.InputBindings>
        <MouseBinding Gesture="LeftDoubleClick"
                      Command="{Binding MyCallback}" />
    </DataGrid.InputBindings>-->
</DataGrid>

I can only allow double click on a DataGridRow.

Any suggestions?

/BR
Steffe


Solution

  • You could replace the event handler with an attached behaviour that executes the command:

    public static class DataGridRowExtensions
    {
        public static readonly DependencyProperty MouseDoubleClickCommandProperty =
            DependencyProperty.RegisterAttached(
                "MouseDoubleClickCommand",
                typeof(ICommand),
                typeof(DataGridRowExtensions),
                new FrameworkPropertyMetadata(default(ICommand), new PropertyChangedCallback(OnSet))
        );
    
        public static ICommand GetMouseDoubleClickCommand(DataGridRow target) =>
            (ICommand)target.GetValue(MouseDoubleClickCommandProperty);
    
        public static void SetMouseDoubleClickCommand(DataGridRow target, ICommand value) =>
            target.SetValue(MouseDoubleClickCommandProperty, value);
    
        private static void OnSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGridRow row = (DataGridRow)d;
            row.MouseDoubleClick += Row_MouseDoubleClick;
        }
    
        private static void Row_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            DataGridRow row = (DataGridRow)sender;
            ICommand command = GetMouseDoubleClickCommand(row);
            if (command != null)
                command.Execute(default);
        }
    }
    

    XAML:

    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="local:DataGridRowExtensions.MouseDoubleClickCommand"
                Value="{Binding DataContext.MyCallback,
                    RelativeSource={RelativeSource AncestorType=DataGrid}}" />
    </Style>