Home > Blockchain >  Wrong order of redo and undo strokes?
Wrong order of redo and undo strokes?

Time:02-17

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.

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

CodePudding user response:

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.

  • Related