1 year ago

#22286

test-img

j.j. Pita

WPF InkCanvas unable to Select items when using Touch and EditingMode is select and ParentControl.IsManipulationEnabled=True

My question is how to Select items in InkCanvas using Touch when the parent control and inkcanvas IsManipulationEnable = true.

I am experiencing an issue with InkCanvas that will not show the Select adorner and also unable to select item base on the following condition:

  • ParentControl.IsManipulationEnable = true
  • InkCanvas.EditingMode = InkCanvaseEditingMode.Select
  • Using Touch

Also, I follow this example msdn, it also fails to select the items.

See below for reference on what is the issue:

Tried in .Net Framework 4.5 and in .Net 5 My Environment:

  • Windows 10 Version 1909 (OS Build 18363.1556)
  • With a Dell Touch Monitor SX2210T

Sample Code: XAML

    <Window x:Class="InkCanvasSelect.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:InkCanvasSelect"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid   x:Name="touchGrid"
            ManipulationStarting="touchGrid_ManipulationStarting"
            ManipulationDelta="touchGrid_ManipulationDelta"
            ManipulationCompleted="touchGride_ManipulationCompleted">
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ComboBox ItemsSource="{Binding EditingMode}"
                  SelectedItem="{Binding SelectedInkCanvasEditingMode}">
            
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"
                               FontSize="15"
                               Height="20" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <InkCanvas Background="AntiqueWhite"
                   x:Name="ink"
                   IsManipulationEnabled="True"
                   PreviewTouchDown="ink_PreviewTouchDown"
                   PreviewTouchUp="ink_PreviewTouchUp"
                   RenderTransform="{Binding ImageTransform}"
                   Grid.Row="1"/>
    </Grid>
</Window>

CS

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent(); 
        DataContext = this;
        ImageTransform = new MatrixTransform();

        EditingMode.Add(InkCanvasEditingMode.None);
        EditingMode.Add(InkCanvasEditingMode.Ink);
        EditingMode.Add(InkCanvasEditingMode.GestureOnly);
        EditingMode.Add(InkCanvasEditingMode.InkAndGesture);
        EditingMode.Add(InkCanvasEditingMode.EraseByPoint);
        EditingMode.Add(InkCanvasEditingMode.EraseByStroke);
        EditingMode.Add(InkCanvasEditingMode.Select);
    }

    private List<int> dec = new List<int>();
    Point centerPoint;

    private void ink_PreviewTouchDown(object sender, TouchEventArgs e)
    {
        dec.Add(e.TouchDevice.Id);
        if (dec.Count == 1)
        {
            TouchPoint touchPoint = e.GetTouchPoint(ink);
            centerPoint = touchPoint.Position;
        }
        if (dec.Count > 1)
        {
            if (ink.EditingMode != InkCanvasEditingMode.None)
            {
                ink.EditingMode = InkCanvasEditingMode.None;
            }
        }
    }

    private void ink_PreviewTouchUp(object sender, TouchEventArgs e)
    {
        if (dec.Count > 1)
        {
            if (ink.EditingMode == InkCanvasEditingMode.None)
            {
                ink.EditingMode = InkCanvasEditingMode.Ink;
            }
        }
        dec.Remove(e.TouchDevice.Id);
    }

    private void touchGrid_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
    {
        e.ManipulationContainer = ink;
        e.Mode = ManipulationModes.All;
    }

    private void touchGrid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        //
        if (dec.Count < 2) return;
        // two fingers to achieve zoom
        if (dec.Count == 2)
        {
            foreach (Stroke stroke in ink.Strokes)
            {
                Matrix matrix = new Matrix();
                matrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y, centerPoint.X, centerPoint.Y);
                stroke.Transform(matrix, false);
            }
        }
        //three fingers to achieve move
        else if (dec.Count == 3)
        {
            foreach (Stroke stroke in ink.Strokes)
            {
                Matrix matrix = new Matrix();
                matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
                stroke.Transform(matrix, false);
            }
        }
        //other achieve rotate
        else
        {
            ink.ManipulationDelta += InkCanvas_ManipulationDelta;
        }
    }

    private void touchGride_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
    {
        //TODO some thing completed
    }

    private MatrixTransform imageTransform;
    public MatrixTransform ImageTransform
    {
        get { return imageTransform; }
        set
        {
            if (value != imageTransform)
            {
                imageTransform = value;
                RaisePropertyChanged("ImageTransform");
            }
        }
    }

    private List<InkCanvasEditingMode> editingMode = new List<InkCanvasEditingMode>();
    public List<InkCanvasEditingMode> EditingMode
    {
        get { return editingMode; }
        set 
        {
            if (value != editingMode)
            {
                editingMode = value;
                RaisePropertyChanged("EditingMode");
            }
        }
    }

    private InkCanvasEditingMode selectedInkCanvasEditingMode;
    public InkCanvasEditingMode SelectedInkCanvasEditingMode
    {
        get { return selectedInkCanvasEditingMode; }
        set
        {
            if (value != selectedInkCanvasEditingMode)
            {
                ink.EditingMode= selectedInkCanvasEditingMode = value;
                RaisePropertyChanged("SelectedInkCanvasEditingMode");
            }
        }
    }

    private void InkCanvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
    {
        // Ask for manipulations to be reported relative to the canvas
        e.ManipulationContainer = touchGrid;
    }

    private void InkCanvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        ManipulationDelta md = e.DeltaManipulation;
        Vector trans = md.Translation;
        double rotate = md.Rotation;

        Matrix m = imageTransform.Matrix;

        // Find center of element and then transform to get current location of center
        FrameworkElement fe = e.Source as FrameworkElement;
        Point center = new Point(fe.ActualWidth / 2, fe.ActualHeight / 2);
        center = m.Transform(center);

        // Update matrix to reflect translation/rotation
        m.Translate(trans.X, trans.Y);
        m.RotateAt(rotate, center.X, center.Y);

        imageTransform.Matrix = m;
        RaisePropertyChanged("ImageTransform");

        e.Handled = true;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

Solution that worked for me The work around that I found.

  • For the Grid ManipulationCompleted and ManipulationDelta eventHandler

    cancelled the manipulation if 1 touch point

  • referred to the comment in this link by "flipMarch 26, 2012 at 11:32 AM"

flipMarch 26, 2012 at 11:32 AM There is another (and probably better) solution to this problem. Using the ManipulationCompletedEventArgs e.Cancel() function. This will cancel the manipulation and sends finger inputs as mouse events. >private void ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) if (e.TotalManipulation.Translation.X == 0 && e.TotalManipulation.Translation.Y == 0) { e.Cancel(); }

private void touchGrid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
        if (dec.Count <= 1)
        {
            e.Cancel();
            return;
        }
       
        // rest of the code
    }

private void touchGride_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
    {
        if (dec.Count <= 1)
        {
            e.Cancel();
        }
        //TODO some thing completed
    }

.net

wpf

touch

inkcanvas

0 Answers

Your Answer

Accepted video resources