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

RichTextBox behaves strangely when setting content programmatically

5 Answers 475 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Michael Evans
Top achievements
Rank 1
Michael Evans asked on 29 Nov 2010, 09:00 PM
I'm using a RadRichTextBox control using the latest (Q3 2010) version.  I'm having some issues with using the text box when I set the content programmatically.   The application allows the user to enter content and then change the text forecolor, highlight color, bold, italic, underline etc.  When they save, we save their content in our own custom XML format which is then used by another program to display the text with the formatting.  All that works OK.  The problem occurs when they go to edit the text.  I'm taking our XML and then putting the text back into spans, setting all the appropriate formatting flags.  It looks OK at first, but when the user interacts with the text box, there is some unusual behavior, including:
  • There are extra spaces at the end of the displayed text, which take on the formatting of the last span of text, but which can't be erased, and the mouse cursor can't be placed into it.
  • If the user places the cursor at the end and starts typing, the first letter is appended to the end of the text, but the cursor then jumps to the beginning of the text and subsequent characteres are added to the beginning unless the user stops typing and puts the cursor back at the end.
  • It's impossible to select the first character of the text.

These issues make it difficult to work with the control.  It's worth noting that I don't see these issues when starting with a blank document in the control and letting the user type, it only seems to happen when I programmtically set the content.  I've looked at the InlineCollection and the spans all seem to be identical, so I'm thinking it's possible there's something different on the control itself or the document that is not the same.

There's so much code associated with the control that I can't really share what I have, but I can share some snippets.  Here is the declaration of the control in XAML:

 

 

<!-- MESSAGE TEXT BOX -->
<telerik:RadRichTextBox x:Name="RichText1" 
                            Grid.Row="5"
                            Grid.Column="1"
                            BorderBrush="{Binding Path=BorderBrush, ElementName=tbShortName}" 
                            BorderThickness="1" 
                            Loaded="RichText1_Loaded"
                            HorizontalAlignment="Stretch" 
                            Height="185"
                            KeyDown="RichText1_KeyDown"
                            Margin="5"
                            HorizontalScrollBarVisibility="Hidden"
                            CurrentSpanStyleChanged="RichText1_CurrentSpanStyleChanged">
</telerik:RadRichTextBox>

This is the what happens after the screen is loaded:

private void CreateRichTextDocument()
{
    RichText1.Document = new RadDocument();
    RichText1.Document.LayoutMode = DocumentLayoutMode.Paged;
    RichText1.Document.SectionDefaultPageMargin = new Padding(5);
    RichText1.Document.DefaultPageLayoutSettings.Height = 140;
    RichText1.Document.DefaultPageLayoutSettings.Width = 300;
    if (RichText1.Document.Sections.Count == 0) { RichText1.Document.Sections.Add(new Section()); }
    if (RichText1.Document.Sections.First.Blocks.Count == 0) { RichText1.Document.Sections.First.Blocks.Add(new Paragraph()); }
    _messageParagraph = RichText1.Document.Sections.First.Blocks.First as Paragraph;
    _messageParagraph.SpacingAfter = 0;
    Left_Click(null, null);     // default to left-justified
}

Basically, I'm using the Paged mode, then creating a Section, then a Pagragraph underneath that.  I set SpacingAfter to 0 to try to eliminate the space problem mentioned above, but it didn't completely work (although it seemed better).

Any help would be appreciated.

 

 

5 Answers, 1 is accepted

Sort by
0
Iva Toteva
Telerik team
answered on 30 Nov 2010, 05:18 PM
Hi Michael Evans,

We tested the scenario using exactly the code provided but we did not manage to reproduce the problem. However, the behavior you described can be indicative of having null characters imported into the document. Could you please check if you are, by any chance, exporting and importing null characters in your custom XML format provider? That can be caused, for example, by using the GetBuffer() method of a stream to get its content as byte array.
In case that does not help, we would very much appreciate it if you could try exporting the document with one of our format providers (XamlFormatProvider, for example). It will fail to export the document, if the issue is indeed null chars, and there will be an exception to confirm that. On the other hand, successful export of the document will enable us to investigate further. If you feel uncomfortable with sharing your document and code to generate it publicly, you can open a support ticket.

Sincerely yours,
Iva
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Michael Evans
Top achievements
Rank 1
answered on 30 Nov 2010, 09:28 PM
OK, I confirmed that I am not inserting null characters into the spans in the document, so I don't think that is an issue.

I tried using the XamlFormatProvider and verified that that worked.  I got nicely formed Xaml and no exceptions.  I then compared the Xaml that is generated on a "fresh" document to that this generated with a document that I populated.  They were nearly identical.  The only difference I saw is that on a fresh document, an underlined span looked like this:

      <t:Span Text="up? " UnderlineDecoration="Line" />

and when I created an underlined span programmatically, the returned Xaml looked like this:

      <t:Span Text="up? " UnderlineDecoration="" />

I'm not sure why it doesn't say "Line" as well.  When I programmatically change it, I do this:

lineSegmentSpan.UnderlineDecoration =

 

new Telerik.Windows.Documents.UI.TextDecorations.DecorationProviders.LineDecoration();

 

 



Not sure if this is "correct" or not.  Is there a better way to do it? However, I don't think this is the problem, since I see this behavior regardless of whether I have any underlined spans.

The following is some pseudo-code that shows what I do to programmatically set the text:

_messageParagraph.Inlines.Clear();
 foreach (XElement lineSegment in lineElement.Elements(XName.Get("linesegment")))
 {
     try
     {
         string attr = lineSegment.Attribute(XName.Get("attr")).Value;
         string[] attrArray = attr.Split(';');
         string lineSegmentText = lineSegment.Value;
         Span lineSegmentSpan = new Span();
         lineSegmentSpan.Text = lineSegmentText + ((lineSegment.NextNode == null) ? " " : string.Empty); 
         // Set attributes of text (bold, color, etc.) 

            _messageParagraph.Inlines.Add(lineSegmentSpan);
    }
}

This seems pretty straightforward except for the bit with the space.  I found that if I don't add a space to the end of the last space, it throws a nasty unhandled exception if I place my cursor at the end of the text.  That explains why there's an extra space at the end of my text, but not why I can't put my cursor after it.

I'm thinking about saving the Xaml and seeing if I use the import function, if it'll add it correctly.  I'll let you know how that goes.

UPDATE:
Using the generated XAML seemed to work better.  I didn't get the jumping around when typing at the end, but I still saw a space at the end that was underlined, but I couldn't get to.  Weird.
0
Iva Toteva
Telerik team
answered on 02 Dec 2010, 06:19 PM
Hi Michael Evans,

Thank you for the follow-up.
As it comes to the underline issue, the "correct" way to set the underlines is not by creating an underline, but using UnderlineTypes like this:

lineSegmentSpan.UnderlineDecoration = UnderlineTypes.Line;
Otherwise, a line would be created anew for every underline and that will cause performance issues. As a side effect, the format provider will not export it.

As for what you are referring to as "space" at the end of the document, it is possible that it is not a space, but the marker for the end of the paragraph (the place where the formatting symbol for the end of the last paragraph would appear if this.radRichTextBox.ShowFormattingSymbols = True). It would make sense, because it cannot be deleted, you cannot move past it, and as of now, its style cannot be manipulated.
Can you please tell us what error exactly are you trying to avoid by adding a space at the end of the document?

Kind regards,
Iva
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
0
Michael Evans
Top achievements
Rank 1
answered on 02 Dec 2010, 07:19 PM
Thanks for that about the UnderlineDecoration. I had done it the correct way for FontWeight, FontStyle, and BaselineAlignment.  I guess the difference is that the property is UnderlineDecoration and the enumeration is called UnderlineTypes and I didn't connect the two, I went looking for UnderlineDecorations.

I decided to use the formatted Xaml and just import it, instead of building the spans from my XML.  That seems to work pretty good except I do sometimes see, if I have an underlined last span, an extra space at the end which gets underlined.  If that is the paragraph character, then I don't know what I could do to avoid that.  Importing the Xaml fixes the main issue with the cursor jumping around when I type, so I'm not too worried about it.  But, by all means, if you have a way to avoid the extra underlined space at the end, please share it with me.
0
Iva Toteva
Telerik team
answered on 07 Dec 2010, 02:10 PM
Hi Michael Evans,

Unfortunately, there is no neat way to avoid the underlined paragraph symbol at the end.
A possible workaround would be to can add a new Span, which is not underlined, to the end of each paragraph and then add the paragraph to the document. Later, you can find these intervals and remove them.
I am pasting here the code, to show you the approach:

private void LoadDocument()
{
    RadDocument document = new RadDocument();
    Section section = new Section();
 
    for (int i = 0; i < 10; i++)
    {
        Paragraph p = new Paragraph();
        for (int j = 0; j < 10; j++)
        {
            string lineSegmentText = i + "segment" + j;
            Span lineSegmentSpan = new Span();
            lineSegmentSpan.UnderlineDecoration = UnderlineTypes.Line;
            lineSegmentSpan.Text = lineSegmentText;
            p.Inlines.Add(lineSegmentSpan);
            p.Inlines.Add(new Span(" "));
        }
        section.Blocks.Add(p);
    }
    document.Sections.Add(section);
    this.radRichTextBox1.Document = document;
    this.radRichTextBox1.Document.ShowFormattingSymbols = true; //you can remove that, it's just so that you can see how it works
    //assure that the document is measured and has arranged its children before proceeding
    this.radRichTextBox1.UpdateEditorLayout();
}

and the method to remove those additionally added spans:
private void RemoveEmptySpans()
{
    foreach (Paragraph paragraph in this.radRichTextBox1.Document.EnumerateChildrenOfType<Paragraph>())
    {
        Span lastSpan = paragraph.Inlines.Last as Span;
        if (lastSpan != null && lastSpan.Text == " ")
        {
            this.radRichTextBox1.Document.CaretPosition.MoveToInline((InlineLayoutBox)lastSpan.FirstLayoutBox, 0);
            this.radRichTextBox1.Document.Delete(false);
        }               
    }
    this.radRichTextBox1.UpdateEditorLayout();
}

You can call these two methods consecutively and they will behave as expected.
If you have any other questions, do not hesitate to contact us again.

Kind regards,
Iva
the Telerik team
Browse the videos here>> to help you get started with RadControls for Silverlight
Tags
RichTextBox
Asked by
Michael Evans
Top achievements
Rank 1
Answers by
Iva Toteva
Telerik team
Michael Evans
Top achievements
Rank 1
Share this question
or