wpf mvvm binding datagrid command

wpf - Enlace el comando de DoubleClick de DataGrid Row a VM



mvvm binding (4)

¿Por qué no simplemente usas el 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>

Tu comando es algo como esto:

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

EDITAR: ahora uso esto en lugar de Interaction.Triggers :

<DataGrid.InputBindings> <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding Path=MouseDoubleClickCommand}" CommandParameter="{Binding ElementName=myGrd, Path=SelectedItem}" /> </DataGrid.InputBindings>

Tengo un Datagrid y no me gusta mi solución para disparar un comando de doble clic en mi modelo de vista para la fila clicada (también conocida como seleccionada).

Ver:

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

ViewModel:

public ICommand MouseDoubleClickCommand { get { if (mouseDoubleClickCommand == null) { mouseDoubleClickCommand = new RelayCommand<MouseButtonEventArgs>( args => { var sender = args.OriginalSource as DependencyObject; if (sender == null) { return; } var ancestor = VisualTreeHelpers.FindAncestor<DataGridRow>(sender); if (ancestor != null) { MessengerInstance.Send(new FindDetailsMessage(this, SelectedItem.Name, false)); } } ); } return mouseDoubleClickCommand; } }

Quiero deshacerme del código relacionado con la vista (el que tiene el objeto de dependencia y el árbol de ayuda visual) en mi modelo de vista, ya que esto rompe la capacidad de prueba de alguna manera. Pero, por otro lado, evito que algo suceda cuando el usuario no hace clic en una fila sino en el encabezado, por ejemplo.

PD: Intenté echar un vistazo a los comportamientos adjuntos, pero no puedo descargar desde Skydrive en el trabajo, por lo que una solución "integrada" sería lo mejor.


Aquí es cómo podría implementarlo usando un comportamiento adjunto:

EDITAR: ahora registra el comportamiento en DataGridRow lugar de DataGrid para que se ignoren los clics de DataGridHeader .

Comportamiento:

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>

Luego deberá modificar su MouseDoubleClickCommand para eliminar el parámetro MouseButtonEventArgs y reemplazarlo con su tipo SelectedItem .


De manera más simple que cualquiera de las soluciones propuestas aquí.

Estoy usando este.

<!-- requires IsSynchronizedWithCurrentItem for more info on virtualization/perf https://.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>

desde WPF DataGrid: CommandBinding a un doble clic en lugar de usar Eventos


Puede probar esta solución alternativa:

<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> ...................

En este caso, debe especificar DataTemplate para cada columna en DataGrid