Created
February 2, 2013 21:20
-
-
Save differentmatt/4699309 to your computer and use it in GitHub Desktop.
Windows Phone 7 Automatic Hyperlinks in RichTextBox
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* 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