Ответ 1
Почему бы вам просто не использовать drag-n-drop? Создайте сетку, содержащую вашу панель инструментов (например, список перетаскиваемых изображений) и целевую сетку, которая отвечает на команды dragdrop:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox Background="AliceBlue" MouseMove="OnMouseMove">
<ListBox.Resources>
<Style TargetType="{x:Type Image}">
<Setter Property="Width" Value="64" />
<Setter Property="Height" Value="64" />
</Style>
</ListBox.Resources>
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_pawn_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_rook_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_knight_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_bishop_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_queen_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_white_king_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_pawn_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_rook_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_knight_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_bishop_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_queen_T.png" />
<Image Source="http://www.wpclipart.com/recreation/games/chess/chess_set_1/chess_piece_black_king_T.png" />
</ListBox>
<GridSplitter Grid.Column="1" Width="5" Background="LightGray" />
<Grid x:Name="targetGrid" Grid.Column="2" AllowDrop="True" DragEnter="OnDragEnter" DragOver="OnDragMove" DragLeave="OnDragLeave" Drop="OnDrop" Background="Transparent"/>
</Grid>
Для вашего списка требуется обработчик MouseMove для определения того, когда изображение перетаскивается, и ваши обработчики команд просто реагируют на различные события по мере необходимости, клонируя требуемое изображение и перетаскивая их через грань сетки соответственно:
public partial class MainWindow : Window
{
private Image DragImage = null;
public MainWindow()
{
InitializeComponent();
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
// make sure we have an image
var image = e.OriginalSource as Image;
if (image == null)
return;
// make sure we've started dragging
if (e.LeftButton != MouseButtonState.Pressed)
return;
DragDrop.DoDragDrop(image, image, DragDropEffects.Copy);
}
private void OnDragEnter(object sender, DragEventArgs e)
{
// make sure we have an image
if (!e.Data.GetDataPresent(typeof(Image)))
{
e.Effects = DragDropEffects.None;
return;
}
// clone the image
var image = e.Data.GetData(typeof(Image)) as Image;
e.Effects = DragDropEffects.Copy;
this.DragImage = new Image { Source = image.Source, Width=64, Height=64 };
var position = e.GetPosition(this.targetGrid);
this.DragImage.SetValue(Grid.MarginProperty, new Thickness(position.X-32, position.Y-32, 0, 0));
this.DragImage.SetValue(Grid.HorizontalAlignmentProperty, HorizontalAlignment.Left);
this.DragImage.SetValue(Grid.VerticalAlignmentProperty, VerticalAlignment.Top);
this.DragImage.IsHitTestVisible = false; // so we don't try and drop it on itself
// add it to the target grid
targetGrid.Children.Add(this.DragImage);
}
private void OnDragMove(object sender, DragEventArgs e)
{
var position = e.GetPosition(this.targetGrid);
this.DragImage.SetValue(Grid.MarginProperty, new Thickness(position.X - 32, position.Y - 32, 0, 0));
}
private void OnDragLeave(object sender, DragEventArgs e)
{
targetGrid.Children.Remove(this.DragImage);
this.DragImage = null;
}
private void OnDrop(object sender, DragEventArgs e)
{
this.DragImage.IsHitTestVisible = true;
this.DragImage = null;
}
}
Результат:
Я сделал что-то ужасное и уродливое WPF здесь вместо чистого и элегантного MVVM, но вы поняли эту идею. Я также не понимаю, почему вы хотите перетаскивать вещи вокруг Grid вместо Canvas?