WPF数据表格选中行单击事件?

47

我希望在WPF DataGrid中选定某一行后双击该行时可以执行一些代码。我知道datagrid具有MouseDoubleClicked事件和RowSelected事件,但是我没有看到任何“选择的行双击”事件......

你觉得有可能以某种方式捕获这个事件吗?


2
如果您使用Caliburn.Micro和MVVM方法,有一种更好的方法来完成这个任务 - 在双击后获取行信息 - Sevenate
7个回答

65

您可以在 ItemContainerStyle 中添加事件处理程序(该样式应用于行):

<DataGrid ... >
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <EventSetter Event="MouseDoubleClick" Handler="Row_DoubleClick"/>
        </Style>
    </DataGrid.ItemContainerStyle>
    ...
</DataGrid>

然后,在处理程序中,您可以检查行是否已被选择

private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
{
    // execute some code
}

就我所知,我无法让“RoutedEvent”正常工作。我收到了一个错误消息:“在类型'EventSetter'中未找到属性'RoutedEvent'。”通过将RoutedEvent更改为Event,我成功让它正常工作。 - Corey Cole
@CoreyCole,你是对的,那是个错误。感谢你指出来。 - Thomas Levesque
2
我发现将其放在<DataGrid.RowStyle>中可以起作用,而ItemContainerStyle则不行。 - simonalexander2005
4
有没有单击行或单元格的单击事件? - V K
1
@VK你可以使用Event="MouseUp"或者Event="MouseDown" - The Fluffy Robot
显示剩余2条评论

27

在寻找解决方案时,我遇到了这个问题,但答案并没有起作用,可能是因为它们过时了或者我自己的实现有问题。不管怎样,这是对我有效的解决方案。

将MouseDoubleClick事件添加到DataGrid中。

        <DataGrid x:Name="DatagridMovie"
              Width="Auto"
              CanUserAddRows="False"
              CanUserDeleteRows="True"
              IsReadOnly="true"
              ItemsSource="{Binding}"
              MouseDoubleClick="Row_MouseDoubleClick">

并且在这种方法中

private void Row_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{                
    // Ensure row was clicked and not empty space
    var row = ItemsControl.ContainerFromElement((DataGrid)sender,
                                        e.OriginalSource as DependencyObject) as DataGridRow;

     if ( row == null ) return;

    … Stuff();
 }

到目前为止,我还没有发现它有任何问题。 它不会像其他的表格那样出现这样的问题:当你在选择一行之前双击标题或空白空间时,仍然会导致它运行。


2
在返回之前,您可能需要执行 e.handled = True; - simonalexander2005
只有当 DataGrid 的 IsReadOnly=true 时,这才能正常工作。 - Lucy82

5

使用数据绑定和MVVM,您可以像这样完成一键事件(=选定行的selectedItem):

    <Datagrid ItemsSource="{Binding YourObservableCollectionProperty}" 
        SelectedItem="{Binding YourSelectedItemProperty}"> 
     //more...      
    </Datagrid>

CodeBehind:

public partial class YourClass : Window
    {
        public YourClass()
        {
            InitializeComponent();
            this.DataContext = new YourClassViewModel();                      
        }
}

视图模型:

public class YourClassViewModel : INotifyPropertyChanged
{

                public event PropertyChangedEventHandler PropertyChanged;
                public virtual void OnPropertyChanged(string propertyName)
                {
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    }
                }

                private ObservableCollection<YourModelClass> _yourObservableCollectionProperty;
                public ObservableCollection<YourModelClass> YourObservableCollectionProperty
                {
                    get { return _yourObservableCollectionProperty; }
                    set
                    {
                        _yourObservableCollectionProperty = value;
                        OnPropertyChanged("YourObservableCollectionProperty");
                    }
                }

    private YourModelClass _yourSelectedItemProperty;
    public YourModelClass YourSelectedItemProperty
    {   
           get { return _yourSelectedItemProperty; }
           set
           {
                _yourSelectedItemProperty = value;
                OnPropertyChanged("YourSelectedItemProperty");
           }    
    }

//Constructor
public YourClassViewModel()
{

       /*Take your ModelClass instance and ObservableCollection instance here 

and play around with them or move them into a method. Normally your 

observablecollection is the itemssource of your datagrid and your selecteditem 

is your modelclass.*/

    }
        }

4

你可以尝试使用当前单元格变更事件处理程序,它仅在单击一次时起作用,而不是双击,如果这正是你想要的,因为双击可以用于启动编辑单元格或整个行或任何其他过程:

private void datagrid_CurrentCellChanged(object sender, EventArgs e)
    {
        int selected_index = datagrid.SelectedIndex + 1;
        // this is used for debugging and testing.
        //MessageBox.Show("The index of the row for the clicked cell is " + selected_index);

    }

3
你应该使用 SelectionChanged 事件代替。对于此事件,所选索引似乎滞后了。 - toster-cx

2

ItemContainerStyle 没有最佳解决方案,建议使用 RowStyle

您的 XAML 代码如下:

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">        
        <EventSetter Event="MouseDoubleClick" Handler="DataGridRow_MouseDoubleClick"/>
    </Style>
</DataGrid.RowStyle>

在你的代码中:
private void DataGridRow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    //your logic here
}

这似乎更好,但我不确定为什么这是正确的选择 - 有人能详细解释一下吗? - mafu
是的,发送者是 DoubleClicked 行,您可以使用 Item 属性访问绑定到该行的模型,像这样。if (sender is DataGridRow dataGridRow) { dataGridRow.Item.your_model_property,,,, } - Alvaro Pereira

0

使用 rowstyleMouseDoubleClick,就像 Darlan Dieterich 所说的那样。

但是当单元格中有 buttoncheckbox 或其他控件时,它们会处理事件但不会阻止事件传递到行,导致奇怪的行为。在这些情况下,使用 MouseDown 可能更好。

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">        
        <EventSetter Event="MouseDown" Handler="DataGridRow_MouseDown"/>
    </Style>
</DataGrid.RowStyle>

private void DataGridRow_MouseDown(object sender, MouseButtonEventArgs e)
{
    if(e.ClickCount != 2)
    {
        return;
    }
    // code here
            
    e.Handled = true;
}

0
为什么不在发生DoubleClick事件时获取SelectedRow属性并对其进行操作?如果SelectedRow为空,则表示未选择任何行,只需返回即可。
private void Grid_DoubleClick(object sender, RoutedEventArgs e)
{
    if(grid.SelectedRow == null)
        return; // return if there's no row selected

    // do something with the Selected row here
}

3
无法实现。用户可以先选择行,然后在空白区域双击。 - Ivan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接