Search code examples
wpfhyperlinkinsertformattingflowdocument

FlowDocument: Insert Hyperlink and keep formatting


How do you insert a HyperLink into a FlowDocument at a specific position? The new HyperLink should have the same formatting as the surrounding text - except for color (should always be blue) and underline (should always be underlined). After inserting the HyperLink, the cursor should be right after the new HyperLink.

Things I've tried:

TextPointer caretPosition = richTextBox.CaretPosition;
TextPointer insertPosition = caretPosition.IsAtInsertionPosition ? caretPosition : caretPosition.GetInsertionPosition(LogicalDirection.Forward);
string linkTitle = "Stack Overflow";

Run run = new Run(linkTitle);

Hyperlink link = new Hyperlink(run, insertPosition);
link.IsEnabled = true;
link.NavigateUri = new Uri(@"http://www.stackoverflow.com");

richTextBox.CaretPosition = run.ContentEnd;

This works, but the new Hyperlink does not have the formatting of it's surrounding text.

this.CaretPosition = this.CaretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);
insertPosition.InsertTextInRun(linkTitle);

Hyperlink link = new Hyperlink(insertPosition, insertPosition.GetPositionAtOffset(linkTitle.Length));
link.IsEnabled = true;
link.NavigateUri = new Uri(@"http://www.stackoverflow.com");

TextPointer positionAfterLink = link.ContentEnd.GetPositionAtOffset(1);
if (!positionAfterLink.IsAtInsertionPosition)
    positionAfterLink = caretPosition.GetInsertionPosition(LogicalDirection.Forward);

richTextBox.CaretPosition = positionAfterLink;

This way, the formatting is kept. But sometimes, CaretPosition is not set behind the end of the new link, but stays in front of the new link. Also, it doesn't look very robust to me.

Has anyone successfully done that? What would be the right way to do this?


Solution

  • I would edit your first code.The RichTextBox.Selection is a TextRange having a method called GetPropertyValue allowing you to get some format properties such as FontStyle, FontWeight, FontSize (and I think that's enough). So you can set those achieved format info for the newly created Hyperlink:

    TextPointer caretPosition = richTextBox.CaretPosition;
    TextPointer insertPosition = caretPosition.IsAtInsertionPosition ? 
        caretPosition : caretPosition.GetInsertionPosition(LogicalDirection.Forward);
    string linkTitle = "Stack Overflow";
    //try getting some format info
    var fStyle = (FontStyle) richTextBox.Selection
                                        .GetPropertyValue(Control.FontStyleProperty);
    var fWeight =(FontWeight)richTextBox.Selection
                                       .GetPropertyValue(Control.FontWeightProperty);
    var fSize = (double)richTextBox.Selection
                                   .GetPropertyValue(Control.FontSizeProperty);
    //create new link
    Run run = new Run(linkTitle);
    Hyperlink link = new Hyperlink(run, insertPosition);
    link.FontStyle = fStyle;
    link.FontWeight = fWeight;
    link.FontSize = fSize;
    //Remaining code ...
    

    To make the link have the default style (blue color and underlined), we have to set the RichTextBox's property IsDocumentEnabled to true. Also after inserting, you may want to call Focus() on the RichTextBox.