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

Using Bookmarks Programmatically

9 Answers 162 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
Jasmin
Top achievements
Rank 1
Jasmin asked on 02 Aug 2011, 05:11 PM
I added bookmarks to the document via the UI.
Using 'GetAllBookmarks' function I am able to get a list of the bookmarks.
How to assign a new value to bookmark programmatically (C#)  ?
Is there any example?

Thanks.

9 Answers, 1 is accepted

Sort by
0
Iva Toteva
Telerik team
answered on 06 Aug 2011, 09:48 AM
Hi Jasmin,

In order to replace the content of a bookmark with some text you can use the following method:

private void ReplaceContentOfBookmark(string bookmarkName)
{
    BookmarkRangeStart bookmark = this.editor.Document.GetBookmarkByName(bookmarkName);
    this.editor.Document.Selection.SelectAnnotationRange(bookmark);
    this.editor.Document.Delete(false);
    this.editor.Insert(bookmarksToContent[bookmarkName]);
}

where bookmarksToContent is a Dictionary<string, string> mapping bookmark names to some other content. In this way, the bookmarks themselves will be removed from the document.
If you want to preserve them, just change the text between the BookmarkRangeStart and BookmarkRangeEnd document elements, you can do so like this:
private void changeAllBookmarks_Click(object sender, RoutedEventArgs e)
{
    BookmarkRangeStart[] bookmarks = this.editor.Document.GetAllBookmarks().ToArray<BookmarkRangeStart>();
    DocumentPosition start = new DocumentPosition(this.editor.Document);
    DocumentPosition end = new DocumentPosition(this.editor.Document);
    foreach (BookmarkRangeStart item in bookmarks)
    {
        this.editor.Document.GoToBookmark(item);
          
        start.MoveToInline(item.FirstLayoutBox as InlineLayoutBox, 0);
        end.MoveToInline(item.End.FirstLayoutBox as InlineLayoutBox, 0);
        start.MoveToNextInline();
        this.editor.Document.Selection.SetSelectionStart(start);
        this.editor.Document.Selection.AddSelectionEnd(end);
  
        this.editor.Delete(false);
  
        this.editor.Insert(bookmarksToContent[item.Name]);
    }
}

More information on Bookmarks, BookmarkRangeStart and BookmarkRangeEnd can be found in our online documentation.
However, if you are using bookmarks in order to implement Mail Merge, this is no longer necessary, because RadRichTextBox supports merge fields and merge out of the box.
I hope this helps.

Kind regards,
Iva
the Telerik team

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

0
Anders
Top achievements
Rank 1
answered on 15 Jan 2013, 09:32 AM
Hi Iva,

I'm want to insert a document fragment between the BookmarkRangeStart and BookmarkRangeEnd document elements, and try to use your code example, but it is not working for me.

In order to insert plain text I have to modify your code slightly to also define start position.
this.editor.Document.GoToBookmark(item);
start.MoveToInline(item.FirstLayoutBox as InlineLayoutBox, 0);
end.MoveToInline(item.End.FirstLayoutBox as InlineLayoutBox, 0);
start.MoveToNextInline();
this.editor.Document.Selection.SetSelectionStart(start);
this.editor.Document.Selection.AddSelectionEnd(end);
this.editor.Delete(false);
this.editor.Insert("some text", start);

This will produce the document structure I want (xaml):
<t:BookmarkRangeStart AnnotationID="1" Name="testbookmark" />
<t:Span Text="some text" />
<t:BookmarkRangeEnd AnnotationID="1" />


However when I try to insert a document fragment the fragment is placed below the bookmark end:

this.editor.Insert("some text", start);

is replaced with

var aDocument = new RadDocument();
aDocument.InsertInline(new Span("some text"));
this.radRichTextBox.Document.InsertFragment(new DocumentFragment(aDocument), start);


results in the document (xaml)
<t:BookmarkRangeStart AnnotationID="1" Name="testbookmark" />
<t:BookmarkRangeEnd AnnotationID="1" />
<t:Span Text="some text" />


How can I insert the fragment text between the BookmarkRange tags??
/Anders

0
Anders
Top achievements
Rank 1
answered on 16 Jan 2013, 08:19 AM
Ok, I found a way: I first insert the fragment in a document, then use InsertBookmark with start and end positions that are place first and last  in the document. It is probably not the best way but it seems to work.

DocumentPosition start = new DocumentPosition(fragmentDoc);
DocumentPosition end = new DocumentPosition(fragmentDoc);
 
var allparagrapghs = fragmentDoc.EnumerateChildrenOfType<Paragraph>();
var firstParagraph = allparagrapghs.First();
start.MoveToInline(firstParagraph.Inlines.First());
start.MoveToFirstPositionInParagraph(); // place carret before first inline
 
var lastParagraph = allparagrapghs.Last();
end.MoveToInline(lastParagraph.Inlines.Last());
end.MoveToLastPositionInParagraph(); // place carret after last inline
 
fragmentDoc.InsertBookmark(start, end, "bookmark");
return new DocumentFragment(fragmentDoc);

However, it seems that there is some bug with the insertion of the BookmarkRangeStart if the first already existing element in the paragraph is a bookmark, then the inserted bookmark range is placed after the existing bookmark. Is this a known issue? Maybe it is a problem with the xaml format provider?

/Anders
0
Anders
Top achievements
Rank 1
answered on 16 Jan 2013, 08:39 AM
I have another problem:

When selecting tha content of a bookmark range, and then extracting tha content to either a DocumentFragment or a RadDocument, the bookmarks within the content are removed.

I have a rad document (shorted for brevity):
<t:RadDocument>
  <t:Section>
    <t:Paragraph>
      <t:BookmarkRangeStart AnnotationID="1" Name="OrderList" />
      <t:BookmarkRangeStart AnnotationID="2" Name="1" />
      <t:Span Text="Order1" />
      <t:BookmarkRangeEnd AnnotationID="2" />
    </t:Paragraph>
    <t:Paragraph>
      <t:BookmarkRangeStart AnnotationID="3" Name="2" />
      <t:Span Text="Order2" />
      <t:BookmarkRangeEnd AnnotationID="3" />
    </t:Paragraph>
    <t:Paragraph>
      <t:BookmarkRangeEnd AnnotationID="4" />
    </t:Paragraph>
    <t:Paragraph />
  </t:Section>
</t:RadDocument>

I select content of the OrderList Bookmark range
var orderListBookmark = radRichTextBox.Document.GetBookmarkByName("OrderList");
DocumentPosition start = new DocumentPosition(radRichTextBox.Document);
DocumentPosition end = new DocumentPosition(radRichTextBox.Document);

start.MoveToInline(orderListBookmark);
end.MoveToInline(orderListBookmark.End);
radRichTextBox.Document.Selection.SetSelectionStart(start);
radRichTextBox.Document.Selection.AddSelectionEnd(end);
 
var orderListContentDocument = radRichTextBox.Document.Selection.CreateDocumentFromSelection();
OR
var orderListContentDocument = radRichTextBox.Document.Selection.CopySelectedDocumentElements();

This will produce the following fragment/document
<t:RadDocument>
  <t:Section>
    <t:Paragraph>
      <t:Span Text="Order1" />
    </t:Paragraph>
    <t:Paragraph>
      <t:Span Text="Order2" />
    </t:Paragraph>
    <t:Paragraph />
  </t:Section>
</t:RadDocument>

So the bookmark ranges inside the selection are removed,
How can I preserve them when copying the selection??

/Anders

0
Petya
Telerik team
answered on 18 Jan 2013, 09:19 AM
Hi Anders,

The issue you explained in your first post seems related to a known bug in the RadDocument.InsertFragment(Document Fragment fragment, DocumentPosition position) method. What you can do in order to avoid it is to use the other method for inserting a fragment instead - RadDocument.InsertFragment(DocumentFragment fragment) which inserts the fragment at the caret location, so you should move the caret to the wanted position prior invoking it.

I am not exactly sure what causes the problem described in your second post, but from the looks of the document in your last post, you've managed to solve it.

As for the behavior when copying text containing bookmarks, the result you are observing is the one by design. All DocumentElements have a IsCopyable bool property and it is set to false for BookmarkRangeStart and BookmarkRangeEnd. The reason for that behavior is that if bookmarks were copyable and you copy some text containing a bookmark from the editor and paste it back that would result in unwanted behavior - there would be two bookmarks with the same name for example.

I hope this information is helpful!
 
All the best,
Petya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Daniel
Top achievements
Rank 1
answered on 25 Jul 2018, 06:48 PM

Hi Anders, i have the same problem that you. I need insert text inside bookmarkRangeStart and bookmarkRangeEnd, but preserve bookmark annotation. have you found a solution?

Help me!

 

0
Tanya
Telerik team
answered on 30 Jul 2018, 02:44 PM
Hi Daniel,

Aren't the suggestions from this thread working for you? Replacing the content between bookmark start and end should be a straight-forward task and it could be implemented using the Selection and Positioning APIs of RadRichTextBox. Here is an example code:
var bookmarkStart = this.radRichTextBox.Document.EnumerateChildrenOfType<BookmarkRangeStart>().First();
var bookmarkEnd = bookmarkStart.End;
 
DocumentPosition start = new DocumentPosition(this.radRichTextBox.Document);
start.MoveToInline(bookmarkStart);
start.MoveToNext();
 
DocumentPosition end = new DocumentPosition(this.radRichTextBox.Document);
end.MoveToInline(bookmarkEnd);
end.MoveToPrevious();
 
this.radRichTextBox.Document.Selection.SetSelectionStart(start);
this.radRichTextBox.Document.Selection.AddSelectionEnd(end);
 
this.radRichTextBox.Insert("sample text");

Hope this is helpful.

Regards,
Tanya
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Daniel
Top achievements
Rank 1
answered on 31 Jul 2018, 11:46 AM

HI Tanya, it works, but the last character ins not replaced. I'll try replace it, but if you have idea how to do it would be great!

thank you very much

0
Tanya
Telerik team
answered on 01 Aug 2018, 04:01 PM
Hi Daniel,

Could you please try removing the invocation of the MoveToPrevious() method for the end position? It seems like I left it by mistake, please excuse me for that. 

Regards,
Tanya
Progress Telerik
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
RichTextBox
Asked by
Jasmin
Top achievements
Rank 1
Answers by
Iva Toteva
Telerik team
Anders
Top achievements
Rank 1
Petya
Telerik team
Daniel
Top achievements
Rank 1
Tanya
Telerik team
Daniel
Top achievements
Rank 1
Share this question
or