This is a migrated thread and some comments may be shown as answers.

how to limit the size in RadRichTextBox

7 Answers 395 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
Sanaa
Top achievements
Rank 1
Sanaa asked on 03 May 2011, 07:51 AM
Hi
i'm using RadRichTextBox to let the users put small note Which can apply some Formats on (Bold,Italic,Underline , Bullets ,Numbers , line size)
anyway  the question is can i limit the size at design time likeTextBox ?
because in my way now im waiting until i get the text then i check the length using Export (txtFormatProvider)
Thanks

7 Answers, 1 is accepted

Sort by
0
Mike
Telerik team
answered on 04 May 2011, 01:31 PM
Hello Sanaa,

Unlike the standard TextBox, which handles a simple string, RadRichTextBox is more like the standard RichTextBox and handles a more complex document structure, in our case an instance of RadDocument class. RadDocument holds not only the text but its structure like paragraphs, sections, etc and also formatting - bold italic and so on. Upon exporting, the document is converted to the corresponding format which is string in cases of TXT, HTML and XAML. The major problem here however, is that in each different format this string has different length.

The bottom line is that RadRichTextBox input cannot be limited in length of the text because the length of the text is not known at this point and it is different depending on the different export format. In addition we do not recommend custom implementation of this approach, even though it might be possible, because limiting the text length in RadRichTextBox while typing will result in constant exporting of the document to the specific format to verify the length and this will have a great impact on the performance.

We believe your current approach it quite reasonable and in case you have no other issues you can continue using it. Let us know if you need more information about this issue or if you have other questions.

All the best,
Mike
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Sanaa
Top achievements
Rank 1
answered on 04 May 2011, 01:56 PM
hi Mike
Thanks for  answering me,
As i told you before i need to limit the size of the characters , so i used

DocumentContentChanged and i check if the length is more than specific length(300)
if yes i create a Span put on it the text after removing the extra characters

private void RadDocument_DocumentContentChanged(object sender, EventArgs e)
       {
           string noteText = ExportToText(this.txtNoteText.Document).Trim();
           if (noteText.Length > 300)
           {
               Span span = new Span();
               span.Text = noteText.Substring(1, 300);
               Paragraph paraghraph = new Paragraph();
               paraghraph.SpacingBefore = 0.0;
               paraghraph.SpacingAfter = 0.0;
               paraghraph.Inlines.Add(span);
               Section section = new Section();
               section.Blocks.Add(paraghraph);
               this.txtNoteText.Document.Sections.Add(section);
           }
       }
but my issue is that the cursor will back to the first position in the document , i tried to move it to the last  using moveToLastPositionInDocument but nothing change.
0
Accepted
Iva Toteva
Telerik team
answered on 09 May 2011, 04:36 PM
Hello Sanaa,

When working with the document from RadDocument's API, as well as modifying directly the DocumentElements (Blocks, Sections, Spans, etc), the document is created anew and the caret position is lost. Moreover, the history of the document is reset, so you won't be able to undo/redo the changes you make to the document.
The best solution to both problems would be to delete the additional characters through RadRichTextBox's API. Something like the following code-snippet should do the trick:

private void RadDocument_DocumentContentChanged(object sender, EventArgs e)
{
    string noteText = new TxtFormatProvider().Export(this.txtNoteText.Document).Trim();
    if (noteText.Length > 300)
    {
        document.DocumentContentChanged -= RadDocument_DocumentContentChanged;
        RadDocument document = sender as RadDocument;
        document.CaretPosition.MoveToLastPositionInDocument();
        document.Selection.SetSelectionStart(document.CaretPosition);
        for (int i = 0; i < noteText.Length - 300; i++)
        {
           document.CaretPosition.MoveToPrevious();
        }
        document.Selection.AddSelectionEnd(document.CaretPosition);
        this.txtNoteText.Delete(false);
        document.DocumentContentChanged += RadDocument_DocumentContentChanged;
    }
}

In this way, you will perform only one change to the document (in terms of undo-redo steps).
Note that any changes you make to the document cause the DocumentContentChanged event to be fired. You should unsubscribe from DocumentContentChanged before making the modifications, so that you avoid the risk of causing the event to be triggered too many times.
I hope that helps. 

Regards,
Iva
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Chris
Top achievements
Rank 1
answered on 24 Apr 2012, 07:50 PM
Iva's approach works in theory, but it has a major flaws in reality...

a) If you are checking the length against the TxtDataFormaters trimmed text result and then moving the cursor to a position in the formatted content, that will not work. (this example only works if plain text is being inputted)

b) Chopping or deleting formatted text could be very dangerous. If the content is html or xaml and you simply delete characters after a position, then what happens to the formatted result? Couldn't you be potentially chopping off close tags that cause malformed markup? The content we are editing in the richtextbox is targeted for use outside of Silverlight as well (Word, PDF, and HTML).

Has anyone implemented a reliable solution to limiting the "text" length in a RadRichTextBox? We have requirements to do this and need to come up with something.

If not, I am thinking you have to bite the bullet and include formatting in the check. However the first 3000 characters could all be style setups depending on how much styling the user has implemented.

Update:

I am using a later version of Telerik Controls, but came up with a possible solution. Hmm. I thought, what about using Undo. Tried the following and it seems to work, even on paste (so the DocumentContentChanged event is catching),

private void rtBoxPurpose_DocumentContentChanged(object sender, EventArgs e)
{
       RadRichTextBox rtBox = sender as RadRichTextBox;
  
        string noteText = new TxtFormatProvider().Export(rtBox.Document).Trim();
        if (noteText.Length > maxText)
        {
            rtBox.Document.History.Undo();                
        }
}

Only thing left would be removing the Redo option to make a mess again from the Document.History.

Flaws?
0
Iva Toteva
Telerik team
answered on 27 Apr 2012, 09:03 AM
Hello Chris,

By deleting content in the document, there is no way to mess up the formatting tags that will be exported when you use XamlFormatProvider or HtmlFormatProvider, because you cannot create a malformed document by deleting content of the RadDocument using the API of the editor. In the code sample above, it is the document content that is manipulated and not the exported document.

However, you are right that there may be a better approach. You can handle the CommandExecuting event in the cases when the document content will be increased in length. The commands that can lengthen the document are InsertTextCommand and InsertDocumentFragmentCommand (used internally by the PasteCommand). If you would be allowing only plain text in the document (i.e. no tables or images), you can try using the following code:

void radRichTextBox_CommandExecuting(object sender, Telerik.Windows.Documents.RichTextBoxCommands.CommandExecutingEventArgs e)
{
    RadRichTextBox richTextBox = (RadRichTextBox)sender;
    if (e.Command is InsertTextCommand || e.Command is InsertDocumentFragmentCommand)
    {
        int currentCharacters = provider.Export(this.radRichTextBox.Document).Length;
        int additionalCharacters = 0;
        if (e.Command is InsertTextCommand)
        {
            additionalCharacters += ((string)e.CommandParameter).Length;
        }
        else
        {
            DocumentFragment fragmentToBePasted = (DocumentFragment)e.CommandParameter;
            additionalCharacters += provider.Export(fragmentToBePasted.ToDocument()).Length;
        }
        if (!richTextBox.Document.Selection.IsEmpty) //selected text will be deleted
        {
            additionalCharacters -= richTextBox.Document.Selection.GetSelectedText().Length;
        }
        if (currentCharacters + additionalCharacters > charLimit)
        {
            e.Cancel = true;
        }
    }
}

Please, try this approach and let us know if you find any flaws.

Kind regards,
Iva Toteva
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
Chris
Top achievements
Rank 1
answered on 27 Apr 2012, 05:59 PM
That seems to work as well, thanks for your quick and thorough reply to the issue.

One concern is how many times I am accessing the content in the richtextbox through export() of the provider. In my Undo() approach I was catching the check for extra text after the content was changed (retroactive).

Two benefits were:
a. I need to capture the length of the text to report back an update to the user of the remaining text (counts down until max is reached). I guess I could move that to the CommandExecuting method but it seems weird to update the diplay before it actually occurs (more intuitive to update the current size after it has been changed). So, I did 1 check against the current text length to restrict and to update the remaining characters message.

b. When I was restricting the text afterwards with the Undo() if too big, there was a brief flicker the text typed or pasted in - then it was removed. With your approach the typing or pasting just doesn't occur. Users could think the UI is not responding to the keystroke or paste event.

Do you see reasons why an Undo() approach would be flakey? It seems much more straight forward and exactly what you'd want to happen. Basically, the user changed the content - it was disallowed, so restore to the previous content. Seems very clean to me, unless you see problems and prefer your proactive approach.

At very least there are 2 working options around this and yours has exposed awareness of a slew of Document.RichTextBoxCommands that we can take advantage of.

Also, thanks for setting me straight on the concerns of chopping text (causing malformed markup). That must be some fun code you guys had to come up with to prevent such errors.

0
Boby
Telerik team
answered on 02 May 2012, 11:41 AM
Hi Chris,
Actually Iva suggested her approach trying to avoid text flickering you mentioned in b.. If this fits better your scenario, you can use your approach. Also note that there is no way to clear only the Redo history stack.

Kind regards,
Boby
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Tags
RichTextBox
Asked by
Sanaa
Top achievements
Rank 1
Answers by
Mike
Telerik team
Sanaa
Top achievements
Rank 1
Iva Toteva
Telerik team
Chris
Top achievements
Rank 1
Boby
Telerik team
Share this question
or