I've been struggling with this problem, off and on, for several months. Today, I decided to ask Bing Chat how to do this. I gave Bing the following direction:
write c# code to extend the .net RichTextBox control in a WPF application so that urls are clickable.
Bing provided the following solution...
-----------------------------------------------------------------------------
To extend the .NET RichTextBox control in a WPF application using C# to make URLs clickable, you can use the TextPointer class to find the start and end positions of the URLs in the text. Here’s an example of how to create an extension method for the RichTextBox control:
public static class RichTextBoxExtensions
{
public static void MakeUrlsClickable(this RichTextBox self)
{
TextPointer pointer = self.Document.ContentStart;
while (pointer != null)
{
if (pointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
string textRun = pointer.GetTextInRun(LogicalDirection.Forward);
MatchCollection matches = Regex.Matches(textRun, @"(https?://[^\s]+)");
foreach (Match match in matches)
{
TextPointer start = pointer.GetPositionAtOffset(match.Index);
TextPointer end = start.GetPositionAtOffset(match.Length);
Hyperlink hyperlink = new Hyperlink(start, end);
hyperlink.NavigateUri = new Uri(match.Value);
}
}
pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
}
}
}
You can then use this method on any RichTextBox control in your WPF application. For example, if you have a RichTextBox control named myRichTextBox, you can call the MakeUrlsClickable extension method like this:
myRichTextBox.MakeUrlsClickable();
-----------------------------------------------------------------------------
This answer got me 80% to a solution. In addition to that code, you have to add a setter properly in the XAML code, plus some code behind for that setter.
So, after fiddling with Bing's code, here's what I finally implemented...
-----------------------------------------------------------------------------
In the XAML code:
<RichTextBox>
<RichTextBox.Resources>
<Style TargetType="Hyperlink">
<Setter Property="Cursor" Value="Hand" />
<EventSetter Event="MouseLeftButtonDown" Handler="Hyperlink_MouseLeftButtonDown" />
</Style>
</RichTextBox.Resources>
</RichTextBox>
In the code behind:
private void Hyperlink_MouseLeftButtonDown(object sender, MouseEventArgs e)
{
var hyperlink = (Hyperlink)sender;
Process.Start(new ProcessStartInfo(hyperlink.NavigateUri.ToString())
{
UseShellExecute = true,
});
e.Handled = true;
}
The extension to the RichTextBox control:
namespace RichTextBoxExtensions
{
public static class RichTextBoxExtensions
{
public static void MakeUrlsClickable(this RichTextBox self)
{
TextPointer pointer = self.Document.ContentStart;
while (pointer != null)
{
if (pointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
string textRun = pointer.GetTextInRun(LogicalDirection.Forward);
MatchCollection matches = Regex.Matches(textRun, @"(https?://[^\s]+)");
foreach (Match match in matches.Cast<Match>())
{
TextPointer start = pointer.GetPositionAtOffset(match.Index);
TextPointer end = start.GetPositionAtOffset(match.Length);
Hyperlink hyperlink = new(start, end)
{
NavigateUri = new Uri(match.Value)
};
}
}
pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
}
}
}
If you have a RichTextBox control named myRichTextBox, you can call the MakeUrlsClickable extension method like this:
myRichTextBox.MakeUrlsClickable();