Using Bookmarks Programmatically

6 posts, 0 answers
  1. Jasmin
    Jasmin avatar
    3 posts
    Member since:
    Dec 2010

    Posted 02 Aug 2011 Link to this post

    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.
  2. Iva Toteva
    Admin
    Iva Toteva avatar
    1319 posts

    Posted 06 Aug 2011 Link to this post

    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 >>

  3. DevCraft banner
  4. Anders
    Anders avatar
    3 posts
    Member since:
    Jan 2013

    Posted 15 Jan 2013 Link to this post

    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

  5. Anders
    Anders avatar
    3 posts
    Member since:
    Jan 2013

    Posted 16 Jan 2013 Link to this post

    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
  6. Anders
    Anders avatar
    3 posts
    Member since:
    Jan 2013

    Posted 16 Jan 2013 Link to this post

    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

  7. Petya
    Admin
    Petya avatar
    975 posts

    Posted 18 Jan 2013 Link to this post

    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.

Back to Top
DevCraft banner