Взаимодействие с мышью у детей ListBoxItem (WPF)

У меня есть ListBox с ItemTemplate, который содержит элемент управления, который взаимодействует с мышью. Это влияет на функциональность выбора ListBox, т. Е. Нажатие элемента управления не выбирает элемент. Это связано с тем, что ListBoxItem устанавливает для свойства Handled события мыши значение true в OnMouseLeftButtonDown. Я попробовал следующее

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    e.Handled = false;
}

но ListBoxItem "захватывает" мышь и не дает элементу управления выполнять свое собственное взаимодействие. Тогда у меня была другая идея

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    ((ListBoxItem)VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(this)))).IsSelected = true;
}

что на самом деле работает, но больше похоже на уродливый клочок, чем на элегантное решение. Есть ли лучшие решения, которые не зависят от точного содержимого визуального дерева?

3 ответа

Я полагаю, что MouseLeftButtonDown - это событие туннелирования: вы можете попробовать использовать PreviewMouseLeftButtonDown, выполняя там свою обработку, затем обеспечивая e.Handled = false; как вы уже пытались - это должно сработать!

Надеюсь, это поможет.

Я нашел способ, который является менее сложным:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    base.OnMouseLeftButtonDown(e);
    Selector.SetIsSelected(this, true);
}

Чтобы это имело эффект, элементу управления в ItemTemplate ListBox требуется следующий атрибут XAML:

Selector.IsSelected="{Binding IsSelected, Mode=OneWayToSource, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"

Это поднимает два новых вопроса:

  1. Было бы лучше определить мое собственное свойство зависимости, а не находить присоединенное, которое в данный момент не используется?
  2. Есть ли способ добиться чего-то похожего только в разметке?

Вот одно простое решение, но, к сожалению, обработчик может быть присоединен только в коде, а не в разметке.
Обработчик событий можно добавить с помощью handledEventsToo подпись AddHandler метод:

myListBox.AddHandler(UIElement.MouseDownEvent, 
        new MouseButtonEventHandler(ListBox_MouseDown), true);

Третий параметр выше handledEventsToo что гарантирует, что этот обработчик будет вызываться независимо от того, отмечен ли он как Handled (который ListBoxItem делает в ListBox).

См. Маркировка перенаправленных событий как обработанных и Обработка классов для объяснения.
См. Например, Как Прикрепить к Событию MouseDown на ListBox.

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