How to: Drag and Drop Ink

Example

The following example creates an application that enables the user to drag selected strokes from one InkCanvas to the other.

<Window x:Class="Window1"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    Title="InkDragDropSample" Height="500" Width="700"
    >
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <InkCanvas Name="ic1" AllowDrop="True" 
               Grid.Column="0" Grid.Row="0" 
               Margin="10,10,10,10" Background="AliceBlue" 
               PreviewMouseDown="InkCanvas_PreviewMouseDown" 
               Drop="InkCanvas_Drop"/>

    <InkCanvas Name="ic2" AllowDrop="True" 
               Grid.Column="1" Grid.Row="0" 
               Margin="10,10,10,10" Background="Beige" 
               PreviewMouseDown="InkCanvas_PreviewMouseDown" 
               Drop="InkCanvas_Drop"/>

    <CheckBox Grid.Row="1" 
              Checked="switchToSelect" Unchecked="switchToInk">
      Select Mode
    </CheckBox>
  </Grid>
</Window>
Imports System
Imports System.IO
Imports System.Windows
Imports System.Windows.Ink
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Input
Imports System.Windows.Media

Class Window1
    Inherits Window

    Public Sub New() 
        InitializeComponent()

    End Sub 'New 

    Private Sub InkCanvas_PreviewMouseDown(ByVal sender As Object, _
                                   ByVal e As MouseButtonEventArgs)

        Dim ic As InkCanvas = CType(sender, InkCanvas)

        Dim pt As Point = e.GetPosition(ic)

        ' If the user is moving selected strokes, prepare the strokes to be 
        ' moved to another InkCanvas. 
        If ic.HitTestSelection(pt) = InkCanvasSelectionHitResult.Selection Then 

            Dim selectedStrokes As StrokeCollection = _
                                   ic.GetSelectedStrokes()

            Dim strokesToMove As StrokeCollection = _
                                 selectedStrokes.Clone()

            ' Remove the offset of the selected strokes so they 
            ' are positioned when the strokes are dropped. 
            Dim inkBounds As Rect = strokesToMove.GetBounds()
            TranslateStrokes(strokesToMove, -inkBounds.X, -inkBounds.Y)

            ' Perform drag and drop. 
            Dim ms As New MemoryStream()
            strokesToMove.Save(ms)

            Dim dataObject As New DataObject _
                (StrokeCollection.InkSerializedFormat, ms)

            Dim effects As DragDropEffects = _
                DragDrop.DoDragDrop(ic, dataObject, DragDropEffects.Move)

            If (effects And DragDropEffects.Move) = DragDropEffects.Move Then 

                ' Remove the selected strokes from the current InkCanvas.
                ic.Strokes.Remove(selectedStrokes)
            End If 
        End If 

    End Sub 'OnMouseDown

    Private Sub InkCanvas_Drop(ByVal sender As Object, _
                       ByVal e As DragEventArgs)

        ' Get the strokes that were moved. 
        Dim ic As InkCanvas = CType(sender, InkCanvas)
        Dim ms As MemoryStream = CType(e.Data.GetData( _
                  StrokeCollection.InkSerializedFormat),  _
                  MemoryStream)

        ms.Position = 0
        Dim strokes As New StrokeCollection(ms)

        ' Translate the strokes to the position at which 
        ' they were dropped. 
        Dim pt As Point = e.GetPosition(ic)
        TranslateStrokes(strokes, pt.X, pt.Y)

        ' Add the strokes to the InkCanvas and keep them selected.
        ic.Strokes.Add(strokes)
        ic.Select(strokes)

    End Sub 'OnDrop

    ' Helper method that transletes the specified strokes. 
    Sub TranslateStrokes(ByVal strokes As StrokeCollection, _
                         ByVal x As Double, ByVal y As Double)

        Dim mat As New Matrix()
        mat.Translate(x, y)
        strokes.Transform(mat, False)

    End Sub 'TranslateStrokes


    Private Sub switchToSelect(ByVal sender As Object, _
                       ByVal e As RoutedEventArgs)

        ic1.EditingMode = InkCanvasEditingMode.Select
        ic2.EditingMode = InkCanvasEditingMode.Select 

    End Sub 'switchToSelect


    Private Sub switchToInk(ByVal sender As Object, _
                    ByVal e As RoutedEventArgs)

        ic1.EditingMode = InkCanvasEditingMode.Ink
        ic2.EditingMode = InkCanvasEditingMode.Ink

    End Sub 'switchToInk

End Class 'Window1
using System;
using System.IO;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

public partial class Window1 : Window
{

    public Window1()
    {
        InitializeComponent();
    }

    void InkCanvas_PreviewMouseDown(object sender, MouseEventArgs e)
    {
        InkCanvas ic = (InkCanvas)sender;

        Point pt = e.GetPosition(ic);

        // If the user is moving selected strokes, prepare the strokes to be 
        // moved to another InkCanvas. 
        if (ic.HitTestSelection(pt) == 
            InkCanvasSelectionHitResult.Selection)
        {
            StrokeCollection selectedStrokes = ic.GetSelectedStrokes();
            StrokeCollection strokesToMove = selectedStrokes.Clone();

            // Remove the offset of the selected strokes so they 
            // are positioned when the strokes are dropped.
            Rect inkBounds = strokesToMove.GetBounds();
            TranslateStrokes(strokesToMove, -inkBounds.X, -inkBounds.Y);

            // Perform drag and drop.
            MemoryStream ms = new MemoryStream();
            strokesToMove.Save(ms);
            DataObject dataObject = new DataObject(
                StrokeCollection.InkSerializedFormat, ms);

            DragDropEffects effects = 
                DragDrop.DoDragDrop(ic, dataObject, 
                                    DragDropEffects.Move);

            if ((effects & DragDropEffects.Move) == 
                 DragDropEffects.Move)
            {
                // Remove the selected strokes  
                // from the current InkCanvas.
                ic.Strokes.Remove(selectedStrokes);
            }
        }
    }

    void InkCanvas_Drop(object sender, DragEventArgs e)
    {
        // Get the strokes that were moved.
        InkCanvas ic = (InkCanvas)sender;
        MemoryStream ms = (MemoryStream)e.Data.GetData(
                           StrokeCollection.InkSerializedFormat);
        ms.Position = 0;
        StrokeCollection strokes = new StrokeCollection(ms);

        // Translate the strokes to the position at which 
        // they were dropped.
        Point pt = e.GetPosition(ic);
        TranslateStrokes(strokes, pt.X, pt.Y);

        // Add the strokes to the InkCanvas and keep them selected.
        ic.Strokes.Add(strokes);
        ic.Select(strokes);
    }

    // Helper method that transletes the specified strokes. 
    void TranslateStrokes(StrokeCollection strokes, 
                          double x, double y)
    {
        Matrix mat = new Matrix();
        mat.Translate(x, y);
        strokes.Transform(mat, false);
    }

    void switchToSelect(object sender, RoutedEventArgs e)
    {
        ic1.EditingMode = InkCanvasEditingMode.Select;
        ic2.EditingMode = InkCanvasEditingMode.Select;
    }

    void switchToInk(object sender, RoutedEventArgs e)
    {
        ic1.EditingMode = InkCanvasEditingMode.Ink;
        ic2.EditingMode = InkCanvasEditingMode.Ink;
    }
}