Как заставить RichTextBox Undo работать лучше?

Я пытаюсь написать текстовый редактор, используя RichTextBox. Теперь меня беспокоят функции Undo и, возможно, Redo в RichTextBox.

Когда я начинаю писать в текстовом поле, скажем, 1 минута! если я вызываю метод Undo, все, что он делает, это просто чистка или сброс RichTextBox снова. Как я могу заставить его работать, чтобы он мог работать лучше, например, отменить последнее добавленное слово или последнюю добавленную новую строку... Я имею в виду обычные вещи, которые вы ожидаете от функции отмены. (То же самое относится и к Redo!)

Есть ли свойства или какие-то варианты для достижения этого? Или я должен реализовать свой собственный код?


person Saeid Yazdani    schedule 29.12.2011    source источник


Ответы (2)


Вы можете сохранить самые последние данные, и когда вы хотите отменить, вы можете изменить текущие данные на последние данные! последние данные могут быть установлены в любое время, когда вы хотите!

Я делаю winForm с richTextBox и кнопкой, которая отменяет написанный текст:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace test
{


public partial class Form1 : Form
{
    List<string> LastData = new List<string>();

    int undoCount = 0;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        LastData.Add(richTextBox1.Text);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            richTextBox1.Text = LastData[LastData.Count - undoCount - 1];
            ++undoCount;
        }
        catch { }
    }

    private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        LastData.Add(richTextBox1.Text);
        undoCount = 0;
    }
}
}

но лучшего и организованного способа я не нашел и можно поменять

LastData.Add(richTextBox1.Text);
undoCount = 0;

сохранить новые слова или новую строку

обновление: если вы хотите сохранить Ram, вы можете удалить первые данные в списке после многих отмененных сохранений.

person ahmadali shafiee    schedule 29.12.2011
comment
Я не понял, не могли бы вы привести пример кода, пожалуйста? Я спрашиваю, как я могу иметь точки отмены в моем приложении, которое активно, и пользователь изменяет текст. - person Saeid Yazdani; 29.12.2011
comment
Спасибо, но хорошо... это сложная работа! Вам не кажется, что этот список может стать невероятно большим, если пользователь будет работать с большим количеством текста? Если это единственный способ, добавление таймера и сохранение контента каждый раз также является хорошей идеей. - person Saeid Yazdani; 29.12.2011
comment
@Sean87: Это для многократной отмены (а не только один раз), но если вы хотите отменить только один раз, вы можете использовать строку, а не список для последних данных! - person ahmadali shafiee; 29.12.2011

Просто чтобы перейти от кода Ахмадали - вы можете поместить его в отдельный класс и также реализовать функциональность повтора:

NB. да, он сохраняет весь текст каждый раз, когда изменяется текстовое поле, поэтому вы можете изменить это, если ваше приложение будет использоваться для большого количества текста или если приложение будет открыто в течение длительного периода времени (т. е. дней/недель)

public partial class MainForm : Form
{

    Undoer undoer;

    public MainForm()
    {
        InitializeComponent();

        this.txtBox.TextChanged += new EventHandler( TextBoxTextChanged );
        this.undoer = new Undoer(ref this.txtText);


        // create a context menu
        ContextMenu menu = new ContextMenu();
        menu.MenuItems.AddRange( new MenuItem[] { 
                    new MenuItem("&Undo",  new EventHandler( this.undoer.undo_Click  )),
                    new MenuItem("&Redo",  new EventHandler( this.undoer.redo_Click  ))
        });
        this.txtBox.ContextMenu = menu;

        // or create keypress event 
        this.txtBox.KeyDown += new KeyEventHandler( textBox_KeyDown );
        this.KeyDown  += new KeyEventHandler( textBox_KeyDown );
    }

    protected void TextBoxTextChanged(object sender, EventArgs e)
    {
        undoer.Save();
    }

    protected void textBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        if (e.Modifiers == (System.Windows.Forms.Keys.Control))
        {
            if ( e.KeyCode == Keys.Z )
            {
                this.undoer.Undo();
                e.Handled = true;
            }
            if ( e.KeyCode == Keys.Y )
            {
                this.undoer.Redo();
                e.Handled = true;
            }
        }
    }
}

public class Undoer
{
    protected System.Windows.Forms.RichTextBox txtBox;
    protected List<string> LastData = new List<string>();
    protected int  undoCount = 0;

    protected bool undoing   = false;
    protected bool redoing   = false;


    public Undoer(ref System.Windows.Forms.RichTextBox txtBox)
    {
        this.txtBox = txtBox;
        LastData.Add(txtBox.Text);
    }

    public void undo_Click(object sender, EventArgs e)
    {
        this.Undo();
    }
    public void redo_Click(object sender, EventArgs e)
    {
        this.Redo();
    }

    public void Undo()
    {
        try
        {
            undoing = true;
            ++undoCount;
            txtBox.Text = LastData[LastData.Count - undoCount - 1];
        }
        catch { }
        finally{ this.undoing = false; }
    }
    public void Redo()
    {
        try
        {
            if (undoCount == 0)
                return;

            redoing = true;
            --undoCount;
            txtBox.Text = LastData[LastData.Count - undoCount - 1];
        }
        catch { }
        finally{ this.redoing = false; }
    }

    public void Save()
    {
        if (undoing || redoing)
            return;

        if (LastData[LastData.Count - 1] == txtBox.Text)
            return;

        LastData.Add(txtBox.Text);
        undoCount = 0;
    }
}
person user1657580    schedule 09.09.2012