Вот последовательность событий:
- Ваша мышь перемещается от того места, где вы щелкнули ее по всей панели. Нет событий пожара.
- Ваша мышь достигает края панели и входит в холст. Событие
DragEnter
происходит на Холсте.
- Ваш обработчик
DragEnter
перемещает панель так, что теперь она находится под мышью. Поскольку мышь больше не находится над Canvas (она находится над панелью), происходит событие DragLeave
.
- Ваша мышь двигается дальше, снова достигая края панели. Шаги 2 и 3 повторяются.
Чем быстрее вы двигаете мышь, тем больше событий вы получите.
Суть вашей проблемы заключается в том, что при перетаскивании используется проверка на попадание, и, перемещая панель, вы теряете способность проверки на попадание, чтобы видеть «за» панелью, чтобы узнать, в какой контейнер она сбрасывается.
Решение состоит в том, чтобы использовать собственный код для обработки перетаскивания, что на самом деле совсем не сложно. Механизм тестирования попаданий в WPF достаточно мощный, чтобы выполнять проверку попаданий за текущим объектом, но перетаскивание не использует эту функциональность. Однако вы можете использовать его напрямую, используя перегрузку VisualTreeHelper.HitTest
, которая принимает HitTestFilterCallback
и HitTestResultCallback
. Просто пропустите фильтр, который игнорирует любые попадания в пределах перетаскиваемой панели.
Я обнаружил, что для таких сценариев, как вы описываете, перетаскивание с помощью обработки событий мыши на самом деле проще, чем использование встроенного DoDragDrop, потому что вам не нужно иметь дело со сложностью (DataObject, DragDropEffects, QueryContinueDrag и т. Д.). ). Эта дополнительная сложность очень важна для включения сценариев перетаскивания между приложениями и процессами, но не помогает вам в том, что вы делаете.
Вот простое решение:
- При MouseDown левой кнопкой вниз записать положение (при MouseLeave стереть положение)
- В MouseMove с {левой кнопкой вниз, записанным положением, текущим положением мыши отличается более чем на дельту}, установите флаг о том, что операция перетаскивания выполняется, и захватите мышь
- В MouseMove с выполняемой операцией перетаскивания используйте тестирование нажатия, чтобы определить, где должна находиться ваша панель (игнорируя саму панель), и соответственно отрегулируйте ее родительские элементы и положение.
- В MouseUp с выполняемой операцией перетаскивания отпустите захват мыши и снимите флажок «Операция перетаскивания»
Наслаждайтесь.