DragDrop - События DragEnter/DragLeave продолжают стрелять

Я переношу перетащить/отбросить операцию на Холсте, который, как предполагается, делает что-то, когда объект перетаскивается в и из него. Моя проблема состоит в том, что события DragEnter/DragLeave продолжают стрелять как перемещения мыши, которые объект по нему, не только на вводят/выходят. Чем быстрее мышь перемещается, тем более часто события стреляют.

Холст Событие DragOver перемещает Холст. Главный/Левый из DraggedObject и я думаю, что это могло бы быть моей проблемой, но я не уверен, как я зафиксировал бы это.

13
задан Rachel 13 April 2010 в 20:06
поделиться

1 ответ

Вот последовательность событий:

  1. Ваша мышь перемещается из где вы щелкнули по панели. Никаких событий не срабатывает.
  2. Ваша мышь достигает края панели и входит в холст. Событие DragEnter запускается на холсте.
  3. Ваш обработчик DragEnter перемещает Panel так, чтобы она оказалась под курсором мыши. Поскольку указатель мыши больше не находится над холстом (он находится над панелью), запускается событие DragLeave .
  4. Ваша мышь перемещается дальше, снова достигая края панели. Шаги 2 и 3 повторяются.

Чем быстрее вы перемещаете мышь, тем больше событий вы получите.

Суть вашей проблемы в том, что при перетаскивании используется проверка попадания, и, перемещая панель, вы лишаетесь возможности проверки нажатия, чтобы видеть «за» вашей панелью, чтобы знать, в какой контейнер она сбрасывается.

Решение состоит в том, чтобы использовать свой собственный код для обработки перетаскивания, что на самом деле совсем несложно. Механизм проверки попадания в WPF достаточно мощный, чтобы выполнять проверку попадания за текущим объектом, но перетаскивание не использует эту функциональность. Однако вы можете использовать его напрямую, используя перегрузку VisualTreeHelper.HitTest , которая принимает HitTestFilterCallback и HitTestResultCallback . Просто передайте ему фильтр, который игнорирует любые попадания в перетаскиваемую панель.

Я обнаружил, что для описанных вами сценариев выполнение перетаскивания путем обработки событий мыши на самом деле проще, чем использование встроенного DoDragDrop, потому что вам не нужно иметь дело со сложностью (DataObject, DragDropEffects, QueryContinueDrag и т. Д. ). Эта дополнительная сложность очень важна для включения сценариев перетаскивания между приложениями и процессами, но не помогает вам в том, что вы делаете.

Вот простое решение:

  1. В MouseDown с нажатой левой кнопкой запишите позицию (при MouseLeave удалите позицию)
  2. В MouseMove с {левой кнопкой вниз, позиция записана, текущее положение мыши отличается более чем на дельту } установите флаг, сообщающий о выполнении операции перетаскивания и захватите мышь
  3. В MouseMove с выполняющейся операцией перетаскивания используйте проверку нажатия, чтобы определить, где должна находиться ваша панель (игнорируя саму панель), и соответствующим образом отрегулируйте ее родительские элементы и положение.
  4. В MouseUp с выполняющейся операцией перетаскивания отпустите захват мыши и снимите флаг «выполняется операция перетаскивания»

Наслаждайтесь.

17
ответ дан 1 December 2019 в 22:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: