Два перекрывающихся элемента управления получают одно и то же событие щелчка?

#c# #wpf #xaml

#c# #wpf #xaml

Вопрос:

У меня есть сетка с двумя перекрывающимися пользовательскими элементами управления:

 <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <ControlA Grid.Row="0" Grid.Column="1"
              Grid.RowSpan="2"
              Canvas.ZIndex="1"
              Background="Transparent"/>
    <ControlB Grid.Row="1" Grid.Column="0"
              Grid.ColumnSpan="2"/>
</Grid>
  

Оба имеют поведение щелчка и прокрутки и прослушивают события MouseDown / MouseWheel, ControlB также имеет собственное VisualTree с дочерними элементами управления, которые должны получать эти туннелирующие и пузырьковые события (ControlA довольно проста, но все еще нуждается в этих событиях).

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

Я пытался перехватить события предварительного просмотра и делегировать их дочерним элементам управления, но до сих пор я не нашел способа, который вообще не приводил бы ни к какому поведению, ни к StackOverflow.

 //Does not work
private void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        ControlA.RaiseEvent( new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left){RoutedEvent = MouseDownEvent} );
        ControlB.RaiseEvent( new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left){RoutedEvent = MouseDownEvent} );
    }
  

Должен ли я вручную реализовать VisualTreeHelper.HitTest() и просмотреть визуальное дерево? Должен ли я сделать фоновое значение controlla нулевым и принудительно запускать события для него (поскольку в нем отсутствует VisualTree дочерних элементов), в то время как ControlB может использовать обычное туннелирование и пузырькование?

Как я могу отправлять события естественным образом (чтобы никакие принудительные команды полностью не заменяли систему событий) обоим элементам управления?

Комментарии:

1. Почему бы просто не использовать ControlA.RaiseEvent(e); ?

2. Приводит к рекурсивному StackOverflow, поскольку это увеличило бы сетку. По какой-то причине снова происходит событие предварительного просмотра. Создание новых аргументов предотвратило это. 🤷

3. Если ControlB это не логический потомок ControlA , вы не можете туннелировать или переносить события из одного элемента управления в другой. Вам нужно вызвать эти события вручную.

4. Логически они являются братьями и сестрами, и было бы мало смысла иметь их родительскими / дочерними (в любой конфигурации). Итак, я должен вызывать события, как? Мой опубликованный способ работает не так, как предполагалось. Может быть, я просто использую неправильный синтаксис или метод?