Skip to content

Instantly share code, notes, and snippets.

@differentmatt
Created February 2, 2013 21:20
Show Gist options
  • Save differentmatt/4699309 to your computer and use it in GitHub Desktop.
Save differentmatt/4699309 to your computer and use it in GitHub Desktop.
Windows Phone 7 Automatic Hyperlinks in RichTextBox
/* Automatically detects URLs in a RichTextBox and replaces them with clickable Hyperlinks.
*
* Tested on Windows Phone 7.1 (WP7)
*
* Usage:
* <mynamespace:UrlizerTextBox IsReadOnly="True" Content="Check out http://funnel-app.com"/>
* Or using databinding:
* <mynamespace:UrlizerTextBox IsReadOnly="True" Content="{Binding}"/>
*/
using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace mynamespace
{
public class UrlizerTextBox : RichTextBox
{
// Copied from http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx
private static readonly Regex UrlRegex = new Regex(@"(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?");
public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
"Content",
typeof(string),
typeof(UrlizerTextBox),
new PropertyMetadata(null, OnContentChanged)
);
public string Content
{
get
{
return (string)GetValue(ContentProperty);
}
set
{
SetValue(ContentProperty, value);
}
}
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UrlizerTextBox textBox = d as UrlizerTextBox;
if (textBox == null)
return;
textBox.Blocks.Clear();
string newText = (string)e.NewValue;
if (String.IsNullOrEmpty(newText))
return;
Paragraph paragraph = new Paragraph();
try
{
int lastPos = 0;
foreach (Match match in UrlRegex.Matches(newText))
{
// Copy raw string from the last position up to the match
if (match.Index != lastPos)
{
string rawText = newText.Substring(lastPos, match.Index - lastPos);
paragraph.Inlines.Add(rawText);
}
// Add matched url
string rawUrl = match.Value;
Uri uri = null;
if (!Uri.TryCreate(rawUrl, UriKind.Absolute, out uri))
{
// Attempt to craft a valid url
if (!rawUrl.StartsWith("http://"))
{
Uri.TryCreate("http://" + rawUrl, UriKind.Absolute, out uri);
}
}
if (uri != null)
{
Hyperlink link = new Hyperlink()
{
NavigateUri = uri,
TargetName = "_blank",
};
link.Inlines.Add(rawUrl);
paragraph.Inlines.Add(link);
}
else
{
paragraph.Inlines.Add(rawUrl);
}
// Update the last matched position
lastPos = match.Index + match.Length;
}
// Finally, copy the remainder of the string
if (lastPos < newText.Length)
paragraph.Inlines.Add(newText.Substring(lastPos));
}
catch (Exception)
{
paragraph.Inlines.Clear();
paragraph.Inlines.Add(newText);
}
// Add the paragraph to the RichTextBox.
textBox.Blocks.Add(paragraph);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment