Элемент управления C # и Winforms TextBox: Как я могу изменить текст? - PullRequest
2 голосов
/ 21 апреля 2010

У меня есть обработчик события для события TextBox.TextChanged в моей форме. Чтобы поддержать отмену, я бы хотел выяснить, что именно изменилось в TextBox, чтобы я мог отменить изменение, если пользователь запросит его. (Я знаю, что встроенное текстовое поле поддерживает отмену, но я хотел бы иметь один стек отмены для всего приложения)

Есть ли разумный способ сделать это? Если нет, то есть ли лучший способ поддержки такой функции отмены?

РЕДАКТИРОВАТЬ: Кажется, работает что-то вроде следующего - есть ли лучшие идеи? (В такие времена я действительно хотел бы, чтобы в .NET было что-то вроде алгоритма STL std::mismatch ...

    class TextModification
    {
        private string _OldValue;
        public string OldValue
        {
            get
            {
                return _OldValue;
            }
        }
        private string _NewValue;
        public string NewValue
        {
            get
            {
                return _NewValue;
            }
        }
        private int _Position;
        public int Position
        {
            get
            {
                return _Position;
            }
        }
        public TextModification(string oldValue, string newValue, int position)
        {
            _OldValue = oldValue;
            _NewValue = newValue;
            _Position = position;
        }
        public void RevertTextbox(System.Windows.Forms.TextBox tb)
        {
            tb.Text = tb.Text.Substring(0, Position) + OldValue + tb.Text.Substring(Position + NewValue.Length);
        }
    }

    private Stack<TextModification> changes = new Stack<TextModification>();
    private string OldTBText = "";
    private bool undoing = false;

    private void Undoit()
    {
        if (changes.Count == 0)
            return;
        undoing = true;
        changes.Pop().RevertTextbox(tbFilter);
        OldTBText = tbFilter.Text;
        undoing = false;
    }

    private void UpdateUndoStatus(TextBox caller)
    {
        int changeStartLocation = 0;
        int changeEndTBLocation = caller.Text.Length;
        int changeEndOldLocation = OldTBText.Length;
        while (changeStartLocation < Math.Min(changeEndOldLocation, changeEndTBLocation) &&
            caller.Text[changeStartLocation] == OldTBText[changeStartLocation])
            changeStartLocation++;
        while (changeEndTBLocation > 1 && changeEndOldLocation > 1 &&
            caller.Text[changeEndTBLocation-1] == OldTBText[changeEndOldLocation-1])
        {
            changeEndTBLocation--;
            changeEndOldLocation--;
        }
        changes.Push(new TextModification(
            OldTBText.Substring(changeStartLocation, changeEndOldLocation - changeStartLocation),
            caller.Text.Substring(changeStartLocation, changeEndTBLocation - changeStartLocation),
            changeStartLocation));
        OldTBText = caller.Text;
    }

    private void tbFilter_TextChanged(object sender, EventArgs e)
    {
        if (!undoing)
            UpdateUndoStatus((TextBox)sender);
    }

Ответы [ 4 ]

8 голосов
/ 21 апреля 2010

Возможно, вам лучше использовать события Enter и Leave. При вводе сохраняйте текущий текст в переменной класса, затем при выходе сравнивайте новый текст со старым.

0 голосов
/ 22 апреля 2010

Это, вероятно, излишне для того, что вы пытаетесь выполнить, но CSLA поддерживает отмену n-уровня. CSLA - это отличный фреймворк для бизнес-объектов, написанный Rocky Lhotka. Бизнес-объекты обрабатывают историю отмены и передаются в пользовательский интерфейс через привязку данных.

Переключение вашего приложения на использование CSLA было бы большим обязательством, но другой вариант - просмотреть свободно доступный исходный код, чтобы увидеть, как он его реализовал.

0 голосов
/ 21 апреля 2010

На самом деле, все, о чем я могу думать, это иметь какую-то коллекцию, в которой вы храните разные строковые версии (так что вы можете отменить много раз, а не один раз).Я бы сохранил ссылку на коллекции TextBox в TextBox.Tag, так что его легко хранить / использовать.

Последнее, но не менее важное, вы обновляете свою коллекцию строк во время события TextChange.Не занимая много времени, вы можете вести полную историю, получая предыдущее значение из своей собственной структуры.

0 голосов
/ 21 апреля 2010

Да, не привязывайте его непосредственно к текстовому полю. Состояние вашей формы должно быть в каком-то объекте модели где-то, что не связано напрямую с формой (MVC - это один из способов, другой - MVVM). Разъединяя их таким образом, вы можете сравнивать новое значение текстового поля со значением текущей модели всякий раз, когда поступает запрос на изменение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...