Элемент управления Windows.Forms RichTextBox - избегайте вставки больших данных - PullRequest
0 голосов
/ 15 апреля 2010

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

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

rtcControl.MaxLength = 65536

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

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

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

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

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

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

Ответы [ 2 ]

1 голос
/ 15 апреля 2010

Как насчет этого:

Обработайте событие 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);
   }
}

Кажется, это работает довольно хорошо. Там может быть более элегантное решение.

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

В ответ на его вопрос:

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

С этим кодом он становится немного медленным с текстом> 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);
    }
...