你为什么不直接使用拖放?创建一个包含工具栏的网格(例如要拖动的图像列表)和响应拖放命令的目标网格:
<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,但你明白了。我也不明白你为什么要在网格而不是画布周围拖动东西?