Перенаправленное событие PreviewMouseRightButtonDown и WPF DataGrid

Теперь, в основном, здесь есть два вопроса, позвольте мне мягко представить вам проблему, с которой я столкнулся в данный момент. Допустим, у нас есть обычная DataGrid, и я пытаюсь применить PreviewMouseRightButtonDown в строке для пользовательских функций и в то же время избегайте выбора, так как это расширяет представление Сведения. Я думал, что этот пост поможет; это было направлено на ListView , но с небольшими настройками он должен работать так же, верно?


Почему вы хотите это сделать? Вы можете спросить. Я хочу не открывать Подробности при щелчке правой кнопкой мыши, поскольку в главном разделе "Сведения о проекте" (иногда) происходит длительное путешествие в базу данных, и при щелчке правой кнопкой мыши можно установить только соответствующие bool flag-свойство в представлении модели в коллекции.


MainWindowView.xaml:

<DataGrid AutoGenerateColumns="False" RowDetailsVisibilityMode="VisibleWhenSelected">
    <!-- Columns ommitted for brevity -->
<DataGrid.ItemContainerStyle>
            <Style TargetType="{x:Type DataGridRow}">
            <!-- Since I'm using Caliburn Micro anyway, I'm going to redirect the event to view model. It doesn't really matter, issue exists with EventSetter too. -->
                <Setter Property="cal:Message.Attach" Value="[Event PreviewMouseRightButtonDown] = [Action CheckItem($eventArgs, $source]"/>
            </Style>
        </DataGrid.ItemContainerStyle>
</DataGrid>

MainWindowViewModel.cs:

public void CheckItem(RoutedEventArgs args, object source)
{
    var row = source as DataGridRow;

    if (row != null)
    {
        var item = (ItemViewModel)row.Item;
        item.IsChecked = true;
    }

    args.Handled = true;
}

Время вопросов:

  • Почему RoutingStrategy на RoutedEventArgs перечислены как Direct и не Tunneling? Я думал все Preview события были Tunneling,

  • И что более важно: вышеуказанное решение работает, если я поставлю точку останова внутри CheckItem, выбор не происходит и детали свернуты, все работает как задумано. Если я удалю точку останова, элемент будет выбран, и откроется раздел "Детали", как если бы событие не было остановлено. Почему это происходит? Я думал, что установка Handled в true на RoutedEventArgs следует просто указать, что событие действительно обработано.

[РЕДАКТИРОВАТЬ]

Теперь я нашел обходной обходной путь, я могу просто прикрепить PreviewMouseDown событие:

bool rightClick;

public void MouseDown(object source, MouseEventArgs args)
{
    rightClick = false;

    if (args.RightButton == MouseButtonState.Pressed)
    {
        rightClick = true;
        //do the checking stuff here
    }
}

а затем подключить к SelectionChanged событие:

public void SelectionChanged(DataGrid source, SelectionChangedEventArgs args)
{
    if (rightClick)
        source.SelectedIndex = -1;           
}

Это работает для моего конкретного случая, но субъективно выглядит очень вонючей, поэтому я открыт для любых других предложений. Особенно почему простой eventArgs.Handled = true по событию мыши недостаточно, чтобы подавить выстрел SelectionChanged позже:)

1 ответ

Решение

Обработка PreviewMouseRightButtonUp вместо Down дает желаемый эффект для меня (выбор должен быть сделан вверх, а не вниз?).

На странице msdn для PreviewMouseRightButtonDown говорится, что ее стратегия маршрутизации должна быть "прямой", а на странице " Обзор маршрутизируемых событий" говорится:

Туннельные события также иногда называют предварительными событиями из-за соглашения об именах, которое используется для пар.

Так что, возможно, туннельные события обычно являются предварительными событиями, но это не означает, что предварительные события должны быть туннельными;)

Редактировать:

Если посмотреть на другие события, такие как PreviewMouseDown и MouseDown, то они представляют собой Tunneling и Bubble, хотя, может быть, только события кнопок вправо / влево выполняются как прямые.

Другие вопросы по тегам