WPF DataGrid: привязка CommandBinding к двойному щелчку вместо использования событий

Я знаю, как использовать событие MouseDoubleClick с моим DataGrid для получения выбранного значения, но как вместо этого использовать привязки команд? Таким образом, моя 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 и заменить его соответствующим образом.


person myermian    schedule 06.10.2010    source источник
comment
Вы проверили этот сообщение, предоставляет полное решение...   -  person Aaron McIver    schedule 07.10.2010


Ответы (4)


Здесь нет необходимости в прикрепленных поведениях или пользовательских подклассах 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; }
}
person Mizipzor    schedule 06.11.2013
comment
/ в вашем {Binding CollectionView/} специально? - person Maslow; 23.09.2015
comment
Да, это привязывает его к текущему элементу. Что при использовании с IsSynchronizedWithCurrentItem означает выбранный элемент. Вот сообщение в блоге. - person Mizipzor; 01.10.2015
comment
Очень аккуратное решение. Также не знал о привязке косой черты. Иногда я действительно удивляюсь, откуда люди знают такие вещи. Спасибо! - person Julian Sievers; 14.11.2015
comment
Это хорошее решение. Но здесь есть недостаток. Если дважды щелкнуть заголовок DataGrids, команда все равно будет выполнена. В некоторых сценариях это может быть нежелательно для разработчика. Как это можно решить? - person T.Y. Kucuk; 07.03.2016
comment
Насколько я понимаю, вы можете использовать часть CanExecute реализации ICommand, чтобы определить, является ли переданный параметр допустимым для запуска команды на - person simonalexander2005; 03.06.2016
comment
Когда я использую косую черту для параметра, он всегда передает элемент в первой строке. У меня есть IsSynchronizedWithCurrentItem="True". Сетка привязана к ObservableCollection. Есть ли что-то, что мне не хватает? виртуализация? - person ProfK; 29.11.2016
comment
Я даю +1, но я все равно думаю, что это взлом. - person LukaszTaraszka; 06.10.2017
comment
Обратите внимание, что если IsReadOnly="False" для вашего DataGrid, то при первом нажатии может быть украден механизм выбора. Установите IsReadOnly="True", чтобы исправить это. - person Dmitriy Nemykin; 29.08.2018
comment
Лично мне не нравится Binding CollectionView/. Это заработает, если вы дадите DataGrid имя и в параметре команды привязки мыши сделаете следующее: CommandParameter="{Binding ElementName=SomeGridName, Path=SelectedItem}" - person Tyler B. Long; 16.05.2019
comment
Почему так много черной магии в WPF/XAML? Где документ, чтобы описать, что такое косая черта? - person Joke Huang; 27.04.2021

Другим решением является добавление входных привязок и привязка selectedItem к свойству, чтобы вы знали, какой из них был выбран:

<DataGrid SelectedItem="{Binding SelectedItem}">
      <DataGrid.InputBindings>
          <MouseBinding Gesture="LeftDoubleClick" Command="{Binding SomeCommand}"/>
     </DataGrid.InputBindings>
</DataGrid>
person Tamar Cohen    schedule 01.07.2013
comment
Красиво и элегантно. - person MaYaN; 26.10.2017
comment
Красиво, но есть проблема. Допустим, у вас есть сетка данных с несколькими столбцами, и для последнего столбца не задана ширина = *, и вы дважды щелкаете в крайнем правом углу в дополнительном пространстве после последнего столбца, выбранный элемент не будет обновляться, и он передаст все, что было выбрано до этого. . И если выделенный элемент еще не существует, он будет передан null. - person JMIII; 26.07.2020

Используйте эту библиотеку

Пример привязки к событию datagrid:

<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>
person vortexwolf    schedule 06.10.2010
comment
Мне нравится библиотека, но, кажется, она содержит больше, чем мне нужно (на данный момент). Я посмотрю на библиотеку, и если мне нужно больше, чем команда двойного щелчка, возможно, она будет содержать другие команды, которые я не возражал бы иметь. - person myermian; 16.04.2011
comment
@myermian Вы также можете взглянуть на MVVM Light, у него есть аналогичный класс и другие классы, которые помогают использовать шаблон MVVM. Для меня проще добавить ссылку на библиотеку, чем копировать код, но это спорный вопрос, использовать сторонние библиотеки или писать свои. - person vortexwolf; 16.04.2011

Или вы можете создать производный класс

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}">
person Catalin Pop    schedule 18.04.2012