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
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
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);
}
}
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
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?
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 >>
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.
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 >>