Bind DoubleClick Command from DataGrid Row to VM

后端 未结 4 789
悲&欢浪女
悲&欢浪女 2020-12-25 13:37

I have a Datagrid and don\'t like my workaround to fire a double click command on my viewmodel for the clicked (aka selected) row.

View:

   

        
相关标签:
4条回答
  • 2020-12-25 13:49

    Why don't you simply use the CommandParameter?

    <DataGrid x:Name="myGrd"
              ItemsSource="{Binding SearchItems}"
              SelectedItem="{Binding SelectedItem}"
              SelectionMode="Single"
              SelectionUnit="FullRow">
    
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseDoubleClick">
                <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}"  
                                    CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        ...
    </DataGrid>
    

    Your command is something like this:

    public ICommand MouseDoubleClickCommand
    {
        get
        {
            if (mouseDoubleClickCommand == null)
            {
                mouseDoubleClickCommand = new RelayCommand<SearchItem>(
                    item =>
                    {
                        var selectedItem = item;
                    });
            }
    
            return mouseDoubleClickCommand;
        }
    }
    

    EDIT: I now use this instead of Interaction.Triggers:

    <DataGrid.InputBindings>
        <MouseBinding MouseAction="LeftDoubleClick"
                      Command="{Binding Path=MouseDoubleClickCommand}"
                      CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" />
    </DataGrid.InputBindings>
    
    0 讨论(0)
  • 2020-12-25 13:51

    Way simpler than any of the proposed solutions here.

    I'm using this one.

    <!-- 
    requires IsSynchronizedWithCurrentItem
    for more info on virtualization/perf https://stackoverflow.com/questions/9949358/datagrid-row-virtualization-display-issue 
     -->
            <DataGrid ItemsSource="{Binding SearchItems}" 
                      IsSynchronizedWithCurrentItem="True"
                      AutoGenerateColumns="false" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" EnableRowVirtualization="True"
                      >
    
                <!-- for details on ICollection view (the magic behind {Binding Accounts/} https://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/ -->
    
                <DataGrid.InputBindings>
                    <MouseBinding
                        MouseAction="LeftDoubleClick"
                        Command="{Binding MouseDoubleClickCommand}"
                        CommandParameter="{Binding SearchItems/}" />
                </DataGrid.InputBindings>
            </DataGrid>
    

    from WPF DataGrid: CommandBinding to a double click instead of using Events

    0 讨论(0)
  • 2020-12-25 14:00

    Here is how you could implement it using an attached behaviour:

    EDIT: Now registers behaviour on DataGridRow rather than DataGrid so that DataGridHeader clicks are ignored.

    Behaviour:

    public class Behaviours
    {
        public static DependencyProperty DoubleClickCommandProperty =
           DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(Behaviours),
                                               new PropertyMetadata(DoubleClick_PropertyChanged));
    
        public static void SetDoubleClickCommand(UIElement element, ICommand value)
        {
            element.SetValue(DoubleClickCommandProperty, value);
        }
    
        public static ICommand GetDoubleClickCommand(UIElement element)
        {
            return (ICommand)element.GetValue(DoubleClickCommandProperty);
        }
    
        private static void DoubleClick_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var row = d as DataGridRow;
            if (row == null) return;
    
            if (e.NewValue != null)
            {
                row.AddHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick));
            }
            else
            {
                row.RemoveHandler(DataGridRow.MouseDoubleClickEvent, new RoutedEventHandler(DataGrid_MouseDoubleClick));
            }
        }
    
        private static void DataGrid_MouseDoubleClick(object sender, RoutedEventArgs e)
        {
            var row= sender as DataGridRow;
    
            if (row!= null)
            {
                var cmd = GetDoubleClickCommand(row);
                if (cmd.CanExecute(row.Item))
                    cmd.Execute(row.Item);
            }
        }
    }
    

    Xaml:

        <DataGrid x:Name="grid" EnableRowVirtualization="True"
              SelectedItem="{Binding SelectedItem}"
              SelectionMode="Single"
              SelectionUnit="FullRow" ItemsSource="{Binding SearchItems}">
           <DataGrid.RowStyle>
               <Style TargetType="DataGridRow">
                    <Setter Property="Behaviours.DoubleClickCommand" Value="{Binding ElementName=grid, Path=DataContext.SortStateCommand}"/>
               </Style>
           </DataGrid.RowStyle>
    

    You will then need to modify your MouseDoubleClickCommand to remove the MouseButtonEventArgs parameter and replace it with your SelectedItem type.

    0 讨论(0)
  • 2020-12-25 14:09

    You may try this workaround:

    <DataGrid  EnableRowVirtualization="True"
              ItemsSource="{Binding SearchItems}"
              SelectedItem="{Binding SelectedItem}"
              SelectionMode="Single"
              SelectionUnit="FullRow">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header=".....">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                            <TextBlock .....>
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="MouseDoubleClick">
                                        <cmd:EventToCommand Command="{Binding MouseDoubleClickCommand}" PassEventArgsToCommand="True" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </TextBlock>
                    </DataTemplate>
        ...................
    

    In this case you have to specify DataTemplate for each column in the DataGrid

    0 讨论(0)
提交回复
热议问题