Tuesday, July 26, 2011

Adding a WPF RichTextBox hyperlink at specific character positions?

Adding hyperlinks to a WPF RichTextBox can be achieved at design time in XAML or programmatically at run time.

Hyperlinks are created programmatically via the hyperlink constructor by parsing either the start and end TextPointers or InLine objects. These constructors are not particularly developer friendly unless the developer is programmatically populating a RichTextBox’s FlowDocument from Runs (see here).

In a recent project I need to add a hyperlink for text between predefined character index. For example, I needed a hyperlink for the text located between character positions 100 and 110.  The following extension method enables this.

RichTextBox extension:

namespace ESRI.PrototypeLab.Sample {
   
public static class Extensions
{
       
public static Hyperlink ToHyperlink(this RichTextBox rtb, int start, int
end) {
           
TextPointer
p1 = rtb.ToTextPointer(start);
           
TextPointer
p2 = rtb.ToTextPointer(end);
           
if (p1 == null || p2 == null) { return null
; }
           
return new Hyperlink
(p1, p2);
        }
       
public static TextPointer ToTextPointer(this RichTextBox rtb, int
index) {
           
int
count = 0;
           
TextPointer
position = rtb.Document.ContentStart;
           
while (position != null
) {
               
if (position.GetPointerContext(LogicalDirection.Forward) ==
TextPointerContext
.Text) {
                   
string textRun = position.GetTextInRun(LogicalDirection
.Forward);
                   
int
length = textRun.Length;
                   
if
(count + length > index) {
                       
return
position.GetPositionAtOffset(index - count);
                    }
                    count += length;
                }
                position = position.GetNextContextPosition(
LogicalDirection
.Forward);
            }
           
return null;
        }
    }
}

How to use:

Hyperlink hyperlink = this.RichTextBox.ToHyperlink(100, 110);
hyperlink.Click += (s, e) => {
   
MessageBox.Show("Hyperlink Clicked"
);
};

0 comments:

Post a Comment