NullReferenceException when creating ReadOnlyRange

4 posts, 0 answers
  1. Christoph
    Christoph avatar
    25 posts
    Member since:
    Dec 2011

    Posted 17 Jan 2012 Link to this post


    i am creating readonly ranges using the InsertReadOnlyRange method.
    This works well most of the times.
    However I get a NullReferenceException deeply from the tk-lib code
    with the following stacktrace:

    Telerik.Windows.Documents.dll!Telerik.Windows.Documents.Model.RadDocument.GetCaretInline() Line 1319    C#
         Telerik.Windows.Documents.dll!Telerik.Windows.Documents.Model.RadDocument.GetCurrentSpanStyle() Line 1336 + 0xc bytes    C#
         Telerik.Windows.Documents.dll!Telerik.Windows.Controls.RadRichTextBox.UpdateCurrentStyles() Line 2974 + 0x20 bytes    C#
         Telerik.Windows.Documents.dll!Telerik.Windows.Documents.UI.DocumentWebLayoutPresenter.DoOnCaretLocationChanged() Line 441    C#
        Telerik.Windows.Documents.dll!Telerik.Windows.Documents.UI.DocumentWebLayoutPresenter.DoOnDocumentChanged.AnonymousMethod__6() Line 409 + 0xa bytes    C#

    the line raising the exception goes like:

    //Line 1319 in RadDocument.cs
        SpanLayoutBox previousSpanBox = DocumentStructureCollection.GetPreviousSiblingForDocumentElement(currentSpanBox,
                        currentSpanBox.Parent.AssociatedDocumentElement) as SpanLayoutBox;
                                  //  ^^^^^NullReferenceException: Parent is null sometimes

    "Parent" is null here.
    I noticed that the "null-ness" and the exception only occur if the span is inserted using InsertInline:

    RadDocument doc = editor.Document;
     var span1 = new Span("This text is protected");
    // doc.InsertInline(span1); //this span's spanbox will have no Parent, causing a Null ref
     (doc.Sections.Last.Blocks.Last as Paragraph).Inlines.Add(span1); //this span's spanbox will have a Parent, not causing a Null ref
     DocumentPosition pos3 = new DocumentPosition(doc.DocumentLayoutBox, true);
     var spb1 = span1.FirstLayoutBox as SpanLayoutBox;
     pos3.MoveToInline(spb1, 0);
     DocumentPosition pos4 = new DocumentPosition(doc.DocumentLayoutBox, true);
     pos4.MoveToInline(spb1, spb1.PositionsCountInBox - 1);
     doc.InsertReadOnlyRange(pos3, pos4); // raises Null ref in RadDocument.GetCaretInline if using "doc.InsertInline"

    so my wish to the telerik developpers is to fix this line of code.
    There are circumstances where a spanbox has no Parent layoutbox.
    (E.g. when appending it with InsertInline). So you can't use it to get its previous sibling.
    If you anaylze the stack trace and the surrounding code of "GetCaretInline"
    it's fully OK to null check the Parent property and in this case simply return
    the span associated to the layoutbox "currentSpanBox".

  2. Iva Toteva
    Iva Toteva avatar
    1319 posts

    Posted 23 Jan 2012 Link to this post

    Hi Chris,

    Actually the correct way to insert a Span in the document if the document has already been measured and arranged is through the InsertInline method of RadRichTextBox or RadDocument. (The document is automatically measured and arranged when shown in an editor in the visual tree.) The difference between the analogical methods of RadDocument and RadRichTextBox is that the history stack will be cleared if you use the method of the document - the same goes for the InsertReadOnlyRange method.

    On the other hand, if you add the span directly to the Inlines of a Paragraph, the document structure will become invalid, because the last Inline of a Paragraph must contain the paragraph end symbol which is created automatically on measure.

    To cut the long story short, you can insert read-only text in the document like this:

    string text = "This text is protected";
    DocumentPosition start = new DocumentPosition(this.editor.Document.CaretPosition);

    I have used the methods of the editor, in order to preserve the undo/redo capability.

    In case you want to set some font properties on the text you are inserting, you can also use the InsertInline method passing a Span as a parameter:
    string text = "This text is protected";
    DocumentPosition start = new DocumentPosition(this.editor.Document.CaretPosition);
    this.editor.InsertInline(new Span(text) { FontWeight = FontWeights.Bold, ForeColor = Colors.Blue });

    Kind regards,
    Iva Toteva
    the Telerik team

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

  3. Cameron Molyneux
    Cameron Molyneux avatar
    79 posts
    Member since:
    Jan 2010

    Posted 29 Feb 2012 Link to this post


    I am trying to do this with MergeFields, however I am not inserting the MergeFields when trying to make them readonly.

    I need to get the end position of the MergeField so I can say where the "AddSelectionEnd" is, rather than the caret position which is at the beginning, and since I am not inserting them, the caret isn't moving to the end. Is there a way to achieve this?

  4. Iva Toteva
    Iva Toteva avatar
    1319 posts

    Posted 06 Mar 2012 Link to this post

    Hello Cameron,

    If rangeStart and rangeEnd are the FieldRangeStart and FieldRangeEnd pair, you can navigate positions to them and insert a read-only range in the following way:

    DocumentPosition start = new DocumentPosition(this.editor.Document);
    DocumentPosition end = new DocumentPosition(this.editor.Document);
    InlineLayoutBox inlineLayoutBox = rangeEnd.FirstLayoutBox as InlineLayoutBox;
    InlineLayoutBox nextLayoutBox = inlineLayoutBox.AssociatedInline.NextSibling.FirstLayoutBox as InlineLayoutBox;
    start.MoveToInline(rangeStart.FirstLayoutBox as InlineLayoutBox, 0);
    end.MoveToInline(nextLayoutBox, 0);
    this.editor.Document.InsertReadOnlyRange(start, end);

    I hope this helps.

    Iva Toteva
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
Back to Top