У меня неожиданное поведение в WPF. Вот мой сценарий:
- У меня есть UserControl в окне. Назовем его «Поверхность». На нем есть холст.
- У меня есть второй UserControl. Назовем это «PlayingCard».
- У меня есть элемент управления PlayingCard UserControl, добавленный как дочерний элемент холста поверхности. Визуально он отображается так, как должен, поверх Surface.
Это все настройки для некоторых операций перетаскивания между «поверхностями» в окне. Я начал с индивидуального подключения всех событий перетаскивания в классе Surface, и все работало нормально. Я мог правильно обнаружить элемент управления PlayingCard UserControl под мышью и перетащить его, использовать Adorners для обратной связи и т. Д.
Затем я выделил внутренности перетаскивания в отдельный статический класс. Внезапно UIElement, обнаруженный при щелчке мышью, больше не является PlayingCard, а Surface!
В настоящее время у меня есть ТРИ разных обработчика событий, подключенных к событию Surface PreviewLeftMouseButtonDown, плюс я переопределяю метод OnPreviewLeftMouseButtonDown на Surface. Я ожидал бы согласованного поведения между всеми этими способами обработки этого метода, но я этого не понимаю. Вот результаты:
(1) У меня есть экземпляр класса Test, в котором есть метод, подключенный к событию PreviewLeftMouseButtonDown на поверхности. Это происходит в основном методе окна. Он определяет поверхность, а не воспроизводящуюся карту в качестве источника.
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
TestClass test = new TestClass();
_leftSurface.PreviewMouseLeftButtonDown += test.Test_PreviewMouseLeftButtonDown;
(2) У меня есть статический класс DragDropManager, который также подключен к событию Surface, также в основном методе Window. Он также определяет в качестве источника Surface, а не PlayingCard.
public Window1()
{
InitializeComponent();
TestClass test = new TestClass();
_leftSurface.PreviewMouseLeftButtonDown += test.Test_PreviewMouseLeftButtonDown;
_leftSurface.PreviewMouseMove += DragDropManager.PreviewMouseMove;
(3) Я переопределяю событие Surface OnPreviewLeftMouseButtonDown. Он определяет поверхность как источник:
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
(4) У класса Surface есть собственный обработчик событий, указанный в XML, и он ПРАВИЛЬНО определяет PlayingCard в качестве источника.
<UserControl x:Class="WpfTest.Surface"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Border Name="_border" BorderThickness="4" BorderBrush="Blue">
<Canvas Name="_surface" Background="Black" AllowDrop="True"
ClipToBounds="True"
PreviewMouseMove="Surface_PreviewMouseMove"
PreviewMouseLeftButtonDown="Surface_PreviewMouseLeftButtonDown"
DragOver="Canvas_DragOver" DragLeave="Canvas_DragLeave">
</Canvas>
</Border>
</UserControl>
Единственный обработчик событий, который правильно определяет PlayingCard как MouseButtonEventArgs.Source, - это обработчик событий, который назначается Surface через XML.
Почему я получаю два разных результата? Почему другие обработчики событий неправильно указывают на PlayingCard как на источник?