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

Read only range insert and delete

1 Answer 150 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
Daniel
Top achievements
Rank 1
Daniel asked on 07 Oct 2016, 11:55 AM

Hi,

I need a functionality to allow users to add e a text that cannot be edited but can be deleted. It needs to have different style than ordinary text.

I Implemented it as.

        private void AddHeading(string key)
        {
            if (HeadingsProvider == null)
                return;
            RtbEditor.BeginUndoGroup();
            var box = RtbEditor.Document.GetLayoutBoxByPosition(RtbEditor.Document.CaretPosition.Location);
            var element = box.AssociatedDocumentElement;
            while (element is Inline && !(element is Span))
                element = element.Parent;
            while (element is Inline)
                element = element.Parent;
            var paragraph = element as Paragraph;
            if (paragraph?.IsEmpty == false)
                RtbEditor.InsertParagraph();
            var headings = HeadingsProvider.GetHeadings(key).ToList();
            for (int i = 0; i < headings.Count; i++)
            {
                RtbEditor.Document.Selection.Clear();
                var lStart = RtbEditor.Document.CaretPosition.Location;
                RtbEditor.InsertInline(new Span(" "));
                RtbEditor.ChangeStyleName("HeadingChar", false);
                RtbEditor.Insert(headings[i]);
                RtbEditor.InsertInline(new Span(" "));
                var lEnd = RtbEditor.Document.CaretPosition.Location;
                var start = new DocumentPosition(RtbEditor.Document);
                start.SetPosition(lStart);
                var end = new DocumentPosition(RtbEditor.Document);
                end.SetPosition(lEnd);
                RtbEditor.Document.Selection.AddSelectionStart(start);
                RtbEditor.Document.Selection.AddSelectionEnd(end);
                RtbEditor.InsertReadOnlyRange();
                RtbEditor.Document.Selection.Clear();
                if (i < headings.Count - 1)
                    RtbEditor.InsertParagraph();
            }
            RtbEditor.EndUndoGroup();
        }
        private void RemoveHeading()
        {
            var box = RtbEditor.Document.GetLayoutBoxByPosition(RtbEditor.Document.CaretPosition.Location);
            var span = box.AssociatedDocumentElement as Span;
            if (span == null)
                return;
            var sibling = span.PreviousSibling;
            while (sibling != null && !(sibling is ReadOnlyRangeStart) && !(sibling is ReadOnlyRangeEnd))
                sibling = sibling.PreviousSibling;
            var start = sibling as ReadOnlyRangeStart;
            if (start == null)
                return;
            var end = start.End;
            if (end == null)
                return;
            RtbEditor.Document.CaretPosition.MoveToInline(start);
            var lStart = RtbEditor.Document.CaretPosition.Location;
            RtbEditor.Document.CaretPosition.MoveToInline(end);
            var lEnd = RtbEditor.Document.CaretPosition.Location;
            var pStart = new DocumentPosition(RtbEditor.Document);
            pStart.SetPosition(lStart);
            var pEnd = new DocumentPosition(RtbEditor.Document);
            pEnd.SetPosition(lEnd);
            RtbEditor.BeginUndoGroup();
            RtbEditor.DeleteReadOnlyRange(start);
            RtbEditor.Document.Selection.Clear();
            RtbEditor.Document.Selection.AddSelectionStart(pStart);
            RtbEditor.Document.Selection.AddSelectionEnd(pEnd);
            RtbEditor.Delete(false);
            RtbEditor.EndUndoGroup();
        }

 

The insert part kind of work. I need to insert an empty span before and after so that the special style not propagate when you type after the heading. I tried to insert Span(""), but it crashes the editor... I can live with " ".

The problem is that remove heading does not work. While the ReadOnlyRange is removed, the text is not. It remains in the RTB and it is selected. you need to click on another paragraph and then you can delete it manually, but then you ending with editable heading if you won't delete it manually.

1 Answer, 1 is accepted

Sort by
0
Mihail
Telerik team
answered on 12 Oct 2016, 11:35 AM
Hello Daniel,

I have noticed that you are using the Location property of the caret position in order to create new document positions. The document position class has a constructor that accepts another document position as an argument. It is more suitable for this scenario as it does not translate the location to a position.

Another thing I have noticed is that the document positions are not after beeing used. Please dispose of the positions as they will keep a reference to its owner document and this is considered a memory leak.

Also, you are getting the span and paragraph boxes from the current inline box. The document position has methods called GetCurrentSpanLayoutBox and GetCurrentParagraphBox that will return the correct box if the position is in such box.

Please have in mind that the document positions should be anchored after its creation and restored from that anchor before executing an action with them. Because the document could be modified after the creation of the position and with thus the position became invalid.

I have prepared a simple demo application with some modification to reflect my comments. You can find it as an attachment.

if you have further questions I will be happy to assist.

Regards,
Mihail
Telerik by Progress
Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Tags
RichTextBox
Asked by
Daniel
Top achievements
Rank 1
Answers by
Mihail
Telerik team
Share this question
or