Windows.Forms RichTextBox Control - Избегайте вставки больших данных

У меня есть форма Windows с RichTextBox. Содержимое RichTextBox записывается в поле базы данных, которое не может превышать 64 КБ данных. Для моей цели этого текста более чем достаточно для хранения.

Я установил свойство MaxLength, чтобы не вставлять больше данных, чем разрешено.

rtcControl.MaxLength = 65536

Однако это ограничивает только количество символов, которые разрешено вставлять в текст. Но с накладными расходами на форматирование из Rtf я могу набрать больше текста, чем мне положено. Еще хуже, если я вставлю большое изображение, которое совсем не увеличивает TextLength, но Rtf Length вырастает довольно сильно.

На данный момент я проверяю длину свойства Rtf richttextboxes в событии FormClosing и показываю пользователю сообщение, если оно слишком велико. Однако это всего лишь обходной путь, потому что я хочу запретить помещать в элемент управления больше данных, чем разрешено (например, в текстовом поле, если вы превысите свойство MaxLength, в элемент управления ничего не вставляется, и вы слышите звуковой сигнал по умолчанию ().

Есть идеи, как этого добиться?

Я уже пробовал:

  • используя настраиваемый элемент управления, который расширяет свойство richtextbox и shadows th Rtf для перехвата вставки. Но, кажется, он не выполняется, если я добавляю текст.

  • Даже событие TextChanged не срабатывает, если я наберу что-л. в контроле.


person Jürgen Steinblock    schedule 15.04.2010    source источник


Ответы (2)


Что насчет этого:

Обрабатывайте событие TextChanged и сравнивайте каждый раз, когда оно изменяется. Он запускался для ввода текста и перетаскивания изображения.

private void richTextBox1_TextChanged(object sender, EventArgs e)
{
   if (richTextBox1.Rtf.Length > richTextBox1.MaxLength)
   {
      // do something here - I displayed a label for
      // my example 
      label1.Text = "Text exceeds maximum size";
      label1.ForeColor = Color.Red;
   }
   else
   {
      label1.Text = richTextBox1.Rtf.Length.ToString();
      label1.ForeColor = Color.Red;
   }
}

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


Изменить: я подумал об этом еще немного, и я подозреваю, что вы можете использовать StringBuilder для хранения содержимого richtextbox каждый раз, и если кто-то попытается превысить эту длину, восстановить данные до предыдущего состояния. Я признаю, что это немного взломано, но похоже, что это работает. Что-то вроде этого:

StringBuild sb = new StringBuilder();

private void richTextBox1_TextChanged(object sender, EventArgs e)
{
   if (richTextBox1.Rtf.Length > richTextBox1.MaxLength)
   {
      richTextBox1.Rtf = sb.ToString();
   }
   else
   {
      sb.Insert(0,richTextBox1.Rtf);
   }
}

Кажется, это работает очень хорошо. Возможно, есть более элегантное решение.

person itsmatt    schedule 15.04.2010
comment
Я еще не пробовал, но почему в этом случае вы используете конструктор строк? Могу ли я получить лучшую производительность по сравнению со строкой? - person Jürgen Steinblock; 15.04.2010
comment
@SchlaWiener - Да, наверное, веревочка была бы лучше. Первоначально я думал об использовании StringBuilder для добавления нового материала RTF, но отказался от этой идеи в пользу более простого подхода «копировать все». - person itsmatt; 15.04.2010

В ответ на itsmatt:

Это сработало, за исключением события TextChanged, которое, похоже, не срабатывает в моей среде (не знаю почему). Но поскольку у меня есть собственный элемент управления пользователем, который перемежается с RichTextBox, я смог переопределить вызываемый метод OnTextChanged (). Но код становится немного сложнее, потому что если вы измените текст в методе OnTextChanged (), он будет вызван снова, что приведет к исключению StackOverflowException. Я также хотел, чтобы звуковой сигнал () и положение курсора / выбор должны были запоминаться.

С этим кодом он становится немного медленным с текстом> 30000, но для меня этого достаточно. В любом случае пользователи не должны хранить в нем столько данных.

    private string lastText;
    private string lastRtf;
    private int lastSelectionStart;
    private int lastSelectionLength;

    private bool skipLengthCheck;
    protected override void OnTextChanged(EventArgs e)
    {
        if (Rtf.Length > MaxLength && !skipLengthCheck)
        {
            skipLengthCheck = true;
            Console.WriteLine("MaxLength exceeded");
            System.Media.SystemSounds.Beep.Play();
            int start = lastSelectionStart;
            int length = lastSelectionLength;
            base.Text = lastText;
            base.Rtf = lastRtf;
            SelectionStart = start > 0 ? start - 1 : 0;
            SelectionLength = length;
            skipLengthCheck = false;               
        }
        else
        {
            lastText = Text;
            lastRtf = Rtf;

            base.OnTextChanged(e);
        }

    }

    protected override void OnSelectionChanged(EventArgs e)
    {
        lastSelectionStart = SelectionStart;
        lastSelectionLength = SelectionLength;

        base.OnSelectionChanged(e);
    }
person Jürgen Steinblock    schedule 15.04.2010