Как сделать такой Drag&Drop с preview как на гифке при этом в рамках MVVM?
Есть Canvas с привязанной коллекцией объектов. Каждый объект представляет из себя CustomControl в котором уже реализован обычный Drag&Drop по примеру из этого ответа
Думал при MouseMove делать VisualBrush текущего объекта, рисовать новый прямоугольник этой кистью и уже его перетаскивать. Но ведь Canvas привязан к коллекции и получается, что этот прямоугольник также нужно будет добавлять в коллекцию, чтобы он отобразился.
Ответ
Давайте попробуем подправить код из этого ответа, чтобы он не переносил квадрат в реальности до тех пор, пока вы его не отпустите.
Идея с VisualBrush — хорошая, так нам будет легко «размножать» существующие элементы. А вот добавлять фиктивный элемент в коллекцию нехорошо, в конце-концов, у нас перемещение — забота UI-уровня, а не модели.
Поэтому изменений на VM-уровне не будет вовсе, и это хорошо.
Добавим поверх нашего списка квадратов ещё один уровень. Чтобы он не мешал, сделаем его прозрачным для мыши. Нужно будет привязать размеры обоих элементов, для этого нам понадобится имя и Binding
Добавилось имя у ItemsControl, у DraggableSquare появилась дополнительная привязка (о ней позже), и внизу появился Canvas, содержащий нужный элемент.
Далее, DraggbleSquare. Мы меняем немного нашу внутреннюю логику. UpdatePosition будет теперь вызываться только при отпускании мыши или потере фокуса окна.
void OnDragMove(object sender, MouseEventArgs e)
{
//UpdatePosition(e);
UpdateDraggedSquarePosition(e);
}
void FinishDrag(object sender, MouseEventArgs e)
{
MouseMove -= OnDragMove;
LostMouseCapture -= OnLostCapture;
UpdatePosition(e);
UpdateDraggedSquarePosition(null);
}
Новая часть логики: UpdateDraggedSquarePosition. Для неё нам понадобится новое dependency property DraggedImageContainer, в которое мы в XAML уже положили элемент, представляющий перемещающуюся картинку.
(Поместите это повыше, около RequestMoveCommand.)
#region dp Shape DraggedImageContainer
public Shape DraggedImageContainer
{
get { return (Shape)GetValue(DraggedImageContainerProperty); }
set { SetValue(DraggedImageContainerProperty, value); }
}
public static readonly DependencyProperty DraggedImageContainerProperty =
DependencyProperty.Register(
"DraggedImageContainer", typeof(Shape), typeof(DraggableSquare));
#endregion
Собственно сама новая логика:
void UpdateDraggedSquarePosition(MouseEventArgs e)
{
var dragImageContainer = DraggedImageContainer;
if (dragImageContainer == null)
return;
var needVisible = e != null;
var wasVisible = dragImageContainer.Visibility == Visibility.Visible;
// включаем/выключаем видимость перемещаемой картинки
dragImageContainer.Visibility = needVisible ? Visibility.Visible : Visibility.Collapsed;
if (!needVisible) // если мы выключились, нам больше нечего делать
return;
if (!wasVisible) // а если мы были выключены и включились,
{ // нам надо привязать изображение себя
dragImageContainer.Fill = new VisualBrush(this);
dragImageContainer.SetBinding( // а также ширину/высоту
Shape.WidthProperty,
new Binding(nameof(ActualWidth)) { Source = this });
dragImageContainer.SetBinding(
Shape.HeightProperty,
new Binding(nameof(ActualHeight)) { Source = this });
// Binding нужен потому, что наш размер может по идее измениться
}
// перемещаем картинку на нужную позицию
var parent = FindParent
Комментариев нет:
Отправить комментарий