WPF MVVM模式下自动生成列的DataGrid双击事件实现咨询
Absolutely! You can absolutely add a double-click interaction (and keep it MVVM-friendly by using commands instead of code-behind events) to your auto-generated column DataGrid. Here are two clean, compliant approaches tailored to your setup:
方案1:使用Blend行为(最快捷)
This method leverages Microsoft's XAML behaviors package to bind the double-click event directly to a ViewModel command. First, install the Microsoft.Xaml.Behaviors.Wpf NuGet package if you haven't already.
Update your DataGrid XAML to include the trigger:
<DataGrid AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn" CanUserSortColumns="False" GridLinesVisibility="None" CanUserAddRows="False" SelectionUnit="Cell" ItemsSource="{Binding ValuesView}" CellStyle="{StaticResource CellStyle}" CurrentCell="{Binding SelectedValue, Mode=TwoWay}"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDoubleClick"> <i:InvokeCommandAction Command="{Binding CellDoubleClickCommand}" CommandParameter="{Binding CurrentCell, RelativeSource={RelativeSource AncestorType=DataGrid}}"/> </i:EventTrigger> </i:Interaction.Triggers> </DataGrid>
Then define the command in your ViewModel (using a standard RelayCommand implementation—you can write your own or use one from an MVVM framework like Prism/MvvmLight):
public ICommand CellDoubleClickCommand { get; } public YourViewModel() { CellDoubleClickCommand = new RelayCommand<DataGridCellInfo>(ExecuteCellDoubleClick); } private void ExecuteCellDoubleClick(DataGridCellInfo cellInfo) { if (cellInfo.IsValid && cellInfo.Item is DataRowView rowView) { // Access the clicked cell's value using the column's sort member path var cellValue = rowView[cellInfo.Column.SortMemberPath]; // Add your business logic here (e.g., open a detail view, edit the value) } }
方案2:自定义附加属性(无外部依赖)
If you prefer not to add external packages, create a custom attached property to handle the double-click and bind it to your command:
First, create the static extension class:
using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; public static class DataGridCellDoubleClick { public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(DataGridCellDoubleClick), new PropertyMetadata(null, OnCommandChanged)); public static void SetCommand(DependencyObject element, ICommand value) { element.SetValue(CommandProperty, value); } public static ICommand GetCommand(DependencyObject element) { return (ICommand)element.GetValue(CommandProperty); } private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is DataGrid dataGrid) { dataGrid.MouseDoubleClick -= DataGrid_MouseDoubleClick; if (e.NewValue is ICommand command) { dataGrid.MouseDoubleClick += (s, args) => { // Find the clicked cell in the visual tree if (args.OriginalSource is DependencyObject depObj) { var cell = depObj.FindVisualParent<DataGridCell>(); if (cell != null && dataGrid.CurrentCell.IsValid) { command.Execute(dataGrid.CurrentCell); } } }; } } } // Helper method to traverse the visual tree private static T FindVisualParent<T>(this DependencyObject child) where T : DependencyObject { var parent = VisualTreeHelper.GetParent(child); return parent is T parentT ? parentT : parent?.FindVisualParent<T>(); } }
Then attach it to your DataGrid in XAML:
<DataGrid AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn" CanUserSortColumns="False" GridLinesVisibility="None" CanUserAddRows="False" SelectionUnit="Cell" ItemsSource="{Binding ValuesView}" CellStyle="{StaticResource CellStyle}" CurrentCell="{Binding SelectedValue, Mode=TwoWay}" local:DataGridCellDoubleClick.Command="{Binding CellDoubleClickCommand}"/>
Your ViewModel command logic stays identical to the first approach.
Key Notes
- Since your
ItemsSourceis aDataTableview, the cell'sItemwill be aDataRowView—make sure to cast it correctly when accessing values. - With
SelectionUnit="Cell", passingCurrentCellas the command parameter gives you precise access to the clicked cell's context.
内容的提问来源于stack exchange,提问作者Wojciech Szabowicz

