Столкнулся с несколько проблемной задачкой по организации перетаскивания объекта внутри grid’а – внутри canvas’а в гугле масса примеров, внутри грида – ноль.
Впринципе все довольно просто, достаточно взять стандартную функцию подходящую для canvas и немного переделать ее для изменения свойства margin вместо указания canvas.top/left, более того так получается даже понятнее и проще. Вот что нам нужно написать в XAML’е:
<Grid Name="parentGrid" SizeChanged="parentGrid_SizeChanged">
<Canvas Name="mainGrid" SizeChanged="mainGrid_SizeChanged">
<Image Name="planImg" Stretch="Fill" />
<Thumb Visibility="Hidden" Cursor="Hand" Opacity="0" Margin="0,0,0,0" Name="thumb1" DragDelta="thumb1_DragDelta" DragStarted="thumb1_DragStarted" DragCompleted="thumb1_DragCompleted"></Thumb>
</Canvas>
</Grid>
- parentGrid – grid внутри которого хотим двигать элемент
- planImg – элемент который хотим двигать, подходит любой элемент внутри нужного нам grid
- thumb1 – это собственно элемент, которым можно легко и непринужденно двигать объектами – смысл в том что у него есть event DragDelta который запускается когда над элементом зажата левая кнопка мышки и курсор изменил свое положение (т.е. произошло перетаскивание). Событие генерирует аргумент DragDeltaEventArgs в котором передает два нужных нам параметра – HorizontalChange и VerticalChange
- thumb1_DragDelta – необходимый нам event, который запускается в процессе перемещения thumb’а
- thumb1_DragStarted – event запускающийся при начале перемещения
- thumb1_DragCompleted – соответственно event запускающийся когда перемещение завершено (по факту отпускания левой кнопки мыши)
Теперь переходим к коду:
private void thumb1_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
thumb1.DataContext = planImg;
}
private void thumb1_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
(thumb1.DataContext as Image).Margin = new Thickness((thumb1.DataContext as Image).Margin.Left + e.HorizontalChange, (thumb1.DataContext as Image).Margin.Top + e.VerticalChange, (thumb1.DataContext as Image).Margin.Right — e.HorizontalChange, (thumb1.DataContext as Image).Margin.Bottom — e.VerticalChange);
thumb1.Margin = new Thickness(thumb1.Margin.Left + e.HorizontalChange, thumb1.Margin.Top + e.VerticalChange, thumb1.Margin.Right — e.HorizontalChange, thumb1.Margin.Bottom — e.VerticalChange);
}
private void thumb1_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
}
Разберем по кускам:
- Вначале мы должны задать DataContext для нашего thumb – по сути мы указываем каким элементом мы хотим двигать. Если мы хотим двигать сразу несколькими элементами то можно либо объеденить их в один общий контейнер (например в Canvas) либо немного изменить функцию dragDelta и сделать прямое обращение к нужным нам элементам (т.е. использовать вместо (thumb1.DataContext as Image) имя нужного элемента и расплодив первую строку функции в зависимости от кол-ва элементов) Обращение через DataContext я использую т.к. в моем проекте thumb управляет перемещением произвольного элемента среди произвольного количества кастомных компонентов – мне так проще делать привязку нежели отлавливать конкретный элемент в дереве.
- Едем дальше – в самой функции DragDelta мы видим две строки – первая строка изменяет свойство Margin нашего управляемого компонента. Если вы перетаскиваете не картинку а например Canvas то логично что вам необходимо изменить as Image на as Canvas. Смысл измений Margin довольно прост – мы берем текущие Margin.Left, Top и т.п. и добавляем (или соотв. вычитаем) к ним значения аргументов HorizontalChange и VerticalChange т.е. собственно текущие дельты перемещения курсора
- Вторая строка этой функции необходима для перемещения самого thumb – самостоятельно он с курсором не перемещается, это кажется не очень логичным, но я допускаю что в ряде случаев этому есть применение (например классический drag-and-drop без “просмотра содержимого окна при перетаскивании”)
- Функцию DragCompleted можно оставить пустой – для непосредственного перемещения компонента по экрану она не нужна.
Вот
Все довольно просто на самом деле )
нечитабельная вёрстка текста
Благодарствую. Весьма помогло