Как обновить положение декоратора перетаскивания во время перетаскивания WPF?

Я использую украшение, чтобы показать «призрак» перетаскиваемого элемента...

var adornerLayer = AdornerLayer.GetAdornerLayer(topLevelGrid);
dragAdorner = new DragAdorner(topLevelGrid, itemToDrag);
adornerLayer.Add(dragAdorner);
dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));

DragDrop.DoDragDrop(sourceItems, viewModel, DragDropEffects.Move);

adornerLayer.Remove(dragAdorner);
itemToDrag = null;

... но я не могу найти хороший способ обновить положение украшения во время перетаскивания. Самое близкое, что у меня есть, это установить AllowDrop="true" в сетке верхнего уровня и дать ему обработчик DragOver...

private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
 dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));
}

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

Кто-нибудь знает лучший способ обновить позицию декоратора?


person IanR    schedule 19.01.2010    source источник


Ответы (3)


Есть это (к сожалению, доступно только как кешированная версия) довольно старая запись в блоге от Беа Столлниц, которая в значительной степени охватывает ваш вопрос. Он имеет хорошую реализацию перетаскивания с декоратором, показывающим «изображение-призрак».

По сути, перетаскивание в WPF — это довольно сложная процедура, которая — если вам нужны пользовательские DragAdorners — включает в себя добавление набора присоединенных свойств зависимостей для обработки настройки всех задействованных событий и особенно для отображения декоратора таким образом, чтобы он не мешал. с выпадающим кодом.

Код Беа работает за счет наличия вспомогательного класса, который устанавливает обработчик событий DragOver и AllowDrop владельца Window непосредственно перед фактической операцией перетаскивания, таким образом, вы можете контролировать все перемещения между фактическим источником перетаскивания и целью перетаскивания.

person Markus Hütter    schedule 20.01.2010

Итак, присмотревшись повнимательнее к коду Беа, который был изменен, он имел в виду...

Я по-прежнему устанавливаю AllowDrop="true" в сетке верхнего уровня и даю ему обработчик DragOver, где я могу обновить положение декоративного элемента, но здесь я также устанавливаю для DragDropEffects значение None. Затем мне просто нужно добавить обработчик DragOver к фактической цели перетаскивания, чтобы также обновить позицию украшения... и убедиться, что установлено e.Handled = true, чтобы обработчик сетки верхнего уровня не просто устанавливал эффекты обратно в None, когда я над мишенью...

private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
 UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
 e.Effects = DragDropEffects.None;
 e.Handled = true;
}

private void DropTarget_OnDragOver(object sender, DragEventArgs e)
{
 UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
 e.Handled = true;
}
person IanR    schedule 21.01.2010
comment
Ссылка сейчас мертва. - person Berin Loritsch; 17.09.2015

Я знаю, что это старый вопрос, но недавно я задал тот же вопрос, а затем должен был ответить на него сам. Я использовал хуки через p/invoke, чтобы получить собственные оконные сообщения до того, как они были использованы операцией перетаскивания. Это позволило мне отслеживать мышь даже во время перетаскивания и без необходимости устанавливать AllowDrop там, где я этого не хотел.

Чтобы получить полный ответ (включая большую часть кода, который я использовал), вы можете проверить мой вопрос:
WPF — отслеживание мыши во время перетаскивания, пока AllowDrop = False

person Keith Stein    schedule 08.08.2019