Let image ManipulationMode capture pointer

Why don’t you just use drag-n-drop? Create a grid containing your toolbar (e.g. a list of images to drag) and a target grid that responds to dragdrop commands:

<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>

Your listbox needs a MouseMove handler to detect when an image is being dragged and your command handlers simply respond to the various events as required, cloning the require image and dragging them across the face of the grid accordingly:

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;
    }

}

Result:

enter image description here

I’ve done things the horrible and ugly WPF way here instead of clean and elegant MVVM, but you get the idea. I also don’t get why you want to drag things around a Grid instead of a Canvas?

Leave a Comment

tech