WPF数据网格:使用CommandBinding代替事件来实现双击

38

我知道如何使用DataGrid的MouseDoubleClick事件获取所选值,但如何使用命令绑定来处理呢?这样我的ViewModel可以处理逻辑。

到目前为止,我有以下内容:

<DataGrid Name="TestGrid" Grid.Row="2" Grid.ColumnSpan="2" AutoGenerateColumns="True" MouseDoubleClick="TestGrid_MouseDoubleClick"
          ItemsSource="{Binding Registrations}" SelectedValue="{Binding CurrentRegistration}" IsReadOnly="True" AlternationCount="2" GridLinesVisibility="None">

我想摆脱MouseDoubleClick并适当地替换它。


你看过这个帖子了吗?它提供了完整的解决方案... - Aaron McIver
4个回答

98

这里不需要使用附加行为或自定义的DataGrid子类。

在你的DataGrid中,将ItemsSource绑定到一个ICollectionView。关键在于设置IsSynchronizedWithCurrentItem="True",这意味着选定的行将成为当前项。

第二部分技巧是使用正斜杠语法将CommandParameter绑定到当前项。

当双击一行时,命令将以所单击的行作为参数执行。

<DataGrid
    ItemsSource="{Binding CollectionView}"
    IsSynchronizedWithCurrentItem="True">
    <DataGrid.InputBindings>
        <MouseBinding
            MouseAction="LeftDoubleClick"
            Command="{Binding DoubleClickCommand}"
            CommandParameter="{Binding CollectionView/}"/>
    </DataGrid.InputBindings>
</DataGrid>

这是一个(简化版)视图模型的样子:

class MyViewModel
{
    public ICollectionView CollectionView { get; set; }

    public ICommand DoubleClickCommand { get; set; }
}

3
你的 {Binding CollectionView/} 中的 / 是有意放置的吗? - Maslow
11
是的,这会将其绑定到当前项。在与 IsSynchronizedWithCurrentItem 一起使用时,意味着选定的项。这是一篇博客文章。 - Mizipzor
5
非常妙的解决方案。我也不知道斜杠绑定这个东西。有时候我真的很惊讶人们是从哪里知道这些东西的。谢谢! - Julian Sievers
4
这是一个不错的解决方案,但是这里有一个缺点。如果双击DataGrid的标题,命令将会被执行。在某些情况下,这可能不是开发人员想要的结果。有什么方法可以解决这个问题? - T.Y. Kucuk
3
注意,如果您的数据表格中 IsReadOnly="False",则第一次单击可能会窃取选择机制。将 IsReadOnly="True" 设置为修复此问题。 - Dmitriy Nemykin
显示剩余5条评论

34

另一个解决方案是添加输入绑定,并将selectedItem绑定到属性,这样您就会知道选择了哪个:

<DataGrid SelectedItem="{Binding SelectedItem}">
      <DataGrid.InputBindings>
          <MouseBinding Gesture="LeftDoubleClick" Command="{Binding SomeCommand}"/>
     </DataGrid.InputBindings>
</DataGrid>

优美而优雅。 - MaYaN
4
不错,但有一个问题。假设您有一个带有多列的数据表格,而最后一列未设置为width=*,如果您双击到最后一列后面的额外空间,所选项目将不会更新,并且它将传递先前所选项目的任何内容。 如果还没有选择任何项目,则会传递空值。 - JMIII

3
使用此库
数据网格事件的示例绑定:
<DataGrid xmlns:command="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
    command:CommandBehavior.Event="MouseDoubleClick"
    command:CommandBehavior.Command="{Binding TestCommand}" />

但是这段代码更好,因为仅在行被点击时触发:
<DataGrid>
    <DataGrid.Resources>
        <Style TargetType="DataGridRow">
            <Setter Property="command:CommandBehavior.Event" Value="MouseDoubleClick"/>
            <Setter Property="command:CommandBehavior.Command" Value="{Binding DataContext.TestCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}"/>
        </Style>
    </DataGrid.Resources>
</DataGrid>

我喜欢这个库,但它似乎包含了我目前不需要的东西。我会查看这个库,如果除了双击命令之外我需要更多的功能,那么也许这个库还包含其他我想要的命令。 - myermian
@myermian 你也可以看看MVVM Light,它有类似的类和其他帮助使用MVVM模式的类。对我来说,添加库引用比复制代码更容易,但是是否使用第三方库或编写自己的库是一个有争议的问题。 - vortexwolf

2

或者,你可以创建一个派生类

public class CustomDataGrid : DataGrid
{
    public ICommand DoubleClickCommand
    {
        get { return (ICommand)GetValue(DoubleClickCommandProperty); }
        set { SetValue(DoubleClickCommandProperty, value); }
    }

    // Using a DependencyProperty as the backing store for DoubleClickCommand.  This    enables animation, styling, binding, etc...
    public static readonly DependencyProperty DoubleClickCommandProperty =
        DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), typeof(CustomDataGrid), new UIPropertyMetadata());

    public CustomDataGrid()
        : base()
    {            
        this.PreviewMouseDoubleClick += new MouseButtonEventHandler(CustomDataGrid_PreviewMouseDoubleClick);
    }


    void CustomDataGrid_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        if (DoubleClickCommand != null)
        {
            DoubleClickCommand.Execute(null);
        }
    }


}

在XAML中,只需绑定到新创建的命令即可。

<CustomDataGrid DoubleClickCommand="{Binding DoubleClickCommand}">

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