Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Wrong order of redo and undo strokes?

I want to implement undo and redo of inkcanvas strokes.

I want to implement redo and undo that can operate multiple times in a row.

I don’t know where is the problem with my code.
Please help me.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

My code is as follows:

xaml:

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="50" />
            <RowDefinition Height="50" />
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <InkCanvas x:Name="inkCanvas" 
                    Grid.Column="0" Grid.ColumnSpan="2"
                    Grid.Row="0" Grid.RowSpan="7"
                    Width="Auto" Height="Auto" EditingMode="Ink"
                    IsHitTestVisible="True"
                    Background="LightSeaGreen"
                    UseCustomCursor="True"
                    Cursor="Pen"/>
        <Button x:Name="btn_Test1"
                 Grid.Row="0"
                 Grid.Column="1"
                 Width="100"
                 Height="50"
                 Content="pen"
                 Cursor="Hand"
                 Tag="Test1"
                 Click="Button_Click" />
        <Button x:Name="btn_Test3"
                 Grid.Row="1"
                 Grid.Column="1"
                 Width="100"
                 Height="50"
                 Content="clear"
                 Tag="Test3"
                 Click="Button_Click" />
        <Button x:Name="btn_Test4"
                 Grid.Row="2"
                 Grid.Column="1"
                 Width="100"
                 Height="50"
                 Content="UnDo"
                 Tag="Undo"
                 Click="Button_Click" />
        <Button x:Name="btn_Test5"
                 Grid.Row="3"
                 Grid.Column="1"
                 Width="100"
                 Height="50"
                 Content="ReDo"
                 Tag="Redo"
                 Click="Button_Click" />
    </Grid>

code behind:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Media;

namespace InkCanvasUndoRedo
{
  public partial class MainWindow : Window
  {
    public Stack<DoStroke> DoStrokes { get; set; }

    public Stack<DoStroke> UndoStrokes { get; set; }

    private bool handle = true;

    public MainWindow()
    {
      InitializeComponent();

      DoStrokes = new Stack<DoStroke>();

      UndoStrokes = new Stack<DoStroke>();

      inkCanvas.DefaultDrawingAttributes.FitToCurve = true;
      inkCanvas.DefaultDrawingAttributes.Color = Color.FromArgb(255, 255, 255, 255);

      inkCanvas.Strokes.StrokesChanged += Strokes_StrokesChanged;
    }

    private void Strokes_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
    {
      if (handle)
      {
        DoStrokes.Push(new DoStroke
        {
          ActionFlag = e.Added.Count > 0 ? "ADD" : "REMOVE",
          Stroke = e.Added.Count > 0 ? e.Added[0] : e.Removed[0]
        });
      }
    }
    public void Undo()
    {
      handle = false;

      if (DoStrokes.Count > 0)
      {
        DoStroke dos = DoStrokes.Pop();
        if (dos.ActionFlag.Equals("ADD"))
        {
          inkCanvas.Strokes.Remove(dos.Stroke);
        }
        else
        {
          inkCanvas.Strokes.Add(dos.Stroke);
        }

        UndoStrokes.Push(dos);
      }
      handle = true;
    }
    public void Redo()
    {
      handle = false;
      if (UndoStrokes.Count > 0)
      {
        DoStroke dos = UndoStrokes.Pop();
        if (dos.ActionFlag.Equals("ADD"))
        {
          inkCanvas.Strokes.Add(dos.Stroke);
        }
        else
        {
          inkCanvas.Strokes.Remove(dos.Stroke);
        }
      }
      handle = true;
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
      switch ((sender as Button).Tag)
      {
        case "Test1":
          inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
          break;
        case "Test3":
          inkCanvas.Strokes.Clear();
          break;

        case "Undo":
          Undo();
          break;
        case "Redo":
          Redo();
          break;
      }
    }
   
  }
  public struct DoStroke
  {
    public string ActionFlag { get; set; }
    public Stroke Stroke { get; set; }
  }
}

The result:
Write: 123

Click: undo->undo->redo->redo->undo

Expected: 3 disappear

Actual: 1 disappears
enter image description here

>Solution :

In your redo Method you do

        DoStroke dos = UndoStrokes.Pop();
        if (dos.ActionFlag.Equals("ADD"))
        {
          inkCanvas.Strokes.Add(dos.Stroke);
        }
        else
        {
          inkCanvas.Strokes.Remove(dos.Stroke);
        }

You should probably call DoStrokes.Push(dos); at the end of this. In a similar way as is done in the Undo-method.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading