Холст в ScrollViewer (предварительный просмотр) Порядок событий MouseButtonDown - PullRequest
3 голосов
/ 28 октября 2011

Если у нас есть

<ScrollViewer Name="scroll_viewer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Canvas Name="canvas" Height="200" Width="200">
        <Rectangle Fill="AliceBlue" Width="100" Height="100"/>  
    </Canvas>
</ScrollViewer> 

с обработчиками для:

scroll_viewer.PreviewMouseLeftButtonDown
scroll_viewer.MouseLeftButtonDown
canvas.PreviewMouseLeftButtonDown

Затем, если мы нажмем прямоугольник, мы получим scroll_viewer_PreviewMouseLeftButtonDown, который сначала вызывается, затем canvas_PreviewMouseLeftButtonDown, но scroll_viewer_MouseLeftButtonDownне вызывается.
Я хочу обработать событие click первым на холсте - если объект щелкают, я хочу обработать событие (для перетаскивания объекта).Если ни один объект холста не нажат, я хочу обработать событие в scroll_viewer (для управления панорамированием scrollview с помощью мыши).
Как управлять этим, учитывая, что порядок вызовов является противоположностью того, что я хочу, и что версия без просмотра scroll_viewer.MouseLeftButtonDown не называется?

ОБНОВЛЕНИЕ:
Из этого поста: Форумы Silverlight

((FrameworkElement)scroll_viewer.GetValue(ScrollViewer.ContentProperty)).MouseLeftButtonDown += scroll_viewer_MouseLeftButtonDown;

РАБОТАЕТ, то есть вызывается ли после событий предварительного просмотра - могут ли некоторые объяснить, почему это меньше, чемочевидный синтаксис требуется?

Ответы [ 2 ]

5 голосов
/ 28 октября 2011

Проблема в том, что ScrollViewer уже обрабатывает событие MouseLeftButtonDown внутри, например:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    if (base.Focus())
        e.Handled = true;
    base.OnMouseLeftButtonDown(e);
}

Вы можете «исправить» это с помощью пользовательского класса, например так:

public class MyScrollViewer : ScrollViewer {

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

СТОРОННОЕ ПРИМЕЧАНИЕ: вы должны использовать x:Name в XAML, а не Name. В противном случае вы можете столкнуться с ошибками компиляции, используя приведенный выше класс.

Кроме того, вы можете прикрепить свой обработчик ко всем MouseLeftButtonDown событиям, включая обработанные. Так что вместо:

this.scroll_viewer.MouseLeftButtonDown += new MouseButtonEventHandler(scroll_viewer_MouseLeftButtonDown);

Вы бы использовали:

this.scroll_viewer.AddHandler(ScrollViewer.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.scroll_viewer_MouseLeftButtonDown), true);
2 голосов
/ 28 октября 2011

События Preview следуют стратегии маршрутизации, аналогичной стратегии Tunneling, это означает, что событие начинается в верхней части дерева элементов и проходит вниз по нему. Так что сначала он попадет в ваш ScrollViewer, а затем в Canvas.

События без предварительного просмотра следуют стратегии маршрутизации, аналогичной стратегии Bubbling, то есть события начинаются на объекте, на котором они произошли, и перемещаются вверх по дереву элементов. В этом случае сначала ударит Canvas, а затем ScrollViewer.

Подробнее о стратегиях маршрутизации вы можете прочитать здесь

В качестве дополнительного примечания, чтобы объекты Canvas были видимыми для событий HitTest, они должны иметь непрозрачный фон. Поэтому, если у вас есть Canvas без заданного цвета фона, по умолчанию он будет прозрачным и не будет отображаться для HitTests.

...