#c# #winforms
Вопрос:
Я пытаюсь отменить и повторить работу в своем текстовом редакторе уже около 3 дней. Это сводит меня с ума.
У меня есть текстовое поле (с именем richTextBoxPrintCtrl1), которое я хотел бы иметь возможность отменить и *повторить *(слово за словом).
Поэтому, если я нажму кнопку отменить, это отменит последнее слово. И если я затем нажму кнопку повторить, она повторит последнее слово.
Может кто-нибудь помочь мне с этим разобраться?
richTextBoxPrintCtrl1.Отменить(); работает не очень хорошо. Он удаляет все, что было введено в текстовое поле. и если вы наберете слишком много, появится эта ошибка
Заранее спасибо за вашу помощь.
Я знаю, что этот вопрос задавался много раз раньше, но я не могу заставить его работать, используя информацию из вопросов, которые я здесь просматривал. если это поможет здесь, мой код
private string[] temp = new string[100];
private int index;
private int currentpostion;
public Undo()
{
index = 0;
currentpostion = 0;
}
public void Set_Text(string s)
{
temp[index] = s;
currentpostion = index;
index;
}
public string UndoCons()
{
if (currentpostion > 0)
{
return temp[--currentpostion];
}
return null;
}
public string RedoCosns()
{
if (currentpostion < index)
{
return temp[ currentpostion];
}
return null;
}
Комментарии:
1. Если вы хотите слово за словом отменить. Вы можете реализовать вход в систему самостоятельно, используя
stack
функцию, в которой вводите все символыstack
и отменяете ввод этого слова/символа для этой функции.2. Я думаю, что самая большая проблема здесь заключается в том, что операции пользовательского интерфейса для расширенного текстового поля не структурированы в словесных единицах. Пользователь может вставлять, удалять и перезаписывать символы , вставлять их из буфера обмена, удалять или перезаписывать выбранные тексты. Это самые маленькие «единицы», которые имеют смысл для отмены/повтора — слова, похоже, не подходят идеально.
Ответ №1:
Добавив комментарий @piedpiper, вы можете посмотреть на шаблон дизайна сувениров (https://refactoring.guru/design-patterns/memento), который является поведенческим паттерном и имеет дело с этим типом функциональности.
Но один из способов подойти к этому-поместить каждое слово в массив/список. Затем у вас есть счетчик позиций, который вы уменьшаете при отмене, а затем объединяете всю строку в массиве до счетчика позиций и заменяете весь текст в текстовом поле объединенной строкой. Та же логика применима и для повтора, когда вы только увеличиваете счетчик позиций.
Вот пример того, как это может сработать. Я использовал форму Windows, RichEditBox, и я отключил свойство ShortcutsEnabled в RichEditBox на значение False.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private IList<Keys> ignoreKeys = new List<Keys> { Keys.Control, Keys.Tab, Keys.Shift, Keys.ControlKey, Keys.ShiftKey, Keys.LShiftKey, Keys.RShiftKey };
private IList<string> Words { get; set; }
private int counter = 0;
public Form1()
{
InitializeComponent();
Words = new List<string>();
}
private void richTextBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control)
{
if (e.KeyCode == Keys.Z)
{
counter--;
}
if (e.KeyCode == Keys.Y)
{
counter ;
}
richTextBox1.Text = String.Join(" ", Words.Take(counter));
}
else if (!ignoreKeys.Any(ignoreKey => ignoreKey == e.KeyCode))
{
Words = richTextBox1.Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
counter = Words.Count;
}
}
}
}
Ответ №2:
Я нашел способ. Я надеюсь, что на этом закончатся все остальные вопросы. код, который у меня сейчас есть, работает :
public class Operation
{
private static List<string> _txt_list = new List<string>() { "" };
private static int Position { get; set; }
public void ChangeText(string txt)
{
if (_txt_list.Count < 100)
{
_txt_list.Add(txt);
//a 0
//al 1
//ali 2
}
else
{
for (int i = 0; i < 100; i )
{
if (i == 99)
{
_txt_list[i] = txt;
}
else
{
_txt_list[i] = _txt_list[i 1];
}
}
}
if (Position < 99)
{
Position = _txt_list.Count -1;
}
}
public string Undo()
{
if (Position > 0)
{
Position--;
}
return _txt_list[Position];
}
public string Redo()
{
if (Position < 99)
{
Position ;
}
return _txt_list[Position];
}
}
Мероприятия:
private void Menu_Edit_Undo_Click(object sender, EventArgs e)
{
txt_Notepad.Text = _operationObj.Undo();
txt_Notepad.SelectionStart = txt_Notepad.Text.Length;
txt_Notepad.SelectionLength = 0;
}
private void Menu_Edit_Redo_Click(object sender, EventArgs e)
{
txt_Notepad.Text = _operationObj.Redo();
txt_Notepad.SelectionStart = txt_Notepad.Text.Length;
txt_Notepad.SelectionLength = 0;
}
изменение текстового поля
private void txt_keyUp(object sender, KeyEventArgs e)
{
_operationObj.ChangeText(txt_Notepad.Text);
}