WinRT TextBlock with HyperLinks
I was doing some experiments with Window 8 app development. I wanted to show the text in a TextBlock with any URL as a clickable hyperlink, so that user can click on it and navigate to that webpage. We can do this easily via xaml as shown below. I googled a lot to find a way to do the same in MVVM approach. With no solution in hand I decided to come up with a solution using Attached Properties.
<TextBlock x:Name="textValue" TextWrapping="Wrap"> <TextBlock.Inlines> <Run Text="This is an example of how Hyperlink can be used in a paragraph of text.
It might be helpful for you look to"></Run> <Hyperlink NavigateUri="www.bing.com">bing</Hyperlink> <Run Text="for more answers in the future."></Run> </TextBlock.Inlines> </TextBlock>
I am using Caliburn Micro to bind the text, so the above approach will not suit my requirement. The solution I come up with is Custom Attached Properties. In the Attached properties I applied the above logic but via code. Have a look at the code.
using System; using System.Text; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Documents;
namespace Test.App.AttachedProps { public class HyperLinkedTextBlock { public static string GetText(TextBlock element) { if (element != null) return element.GetValue(ArticleContentProperty) as string; return string.Empty; } public static void SetText(TextBlock element, string value) { if (element != null) element.SetValue(ArticleContentProperty, value); } public static readonly DependencyProperty ArticleContentProperty = DependencyProperty.RegisterAttached( "Text", typeof(string), typeof(HyperLinkedTextBlock), new PropertyMetadata(null, OnInlineListPropertyChanged)); private static void OnInlineListPropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs e) { var tb = obj as TextBlock; if (tb == null) return; string text = e.NewValue as string; tb.Inlines.Clear(); if (text.ToLower().Contains("http:") || text.ToLower().Contains("www.")) AddInlineControls(tb, SplitSpace(text)); else tb.Inlines.Add(GetRunControl(text)); } private static void AddInlineControls(TextBlock textBlock, string[] splittedString) { for (int i = 0; i < splittedString.Length; i++) { string tmp = splittedString[i]; if (tmp.ToLower().StartsWith("http:") || tmp.ToLower().StartsWith("www.")) textBlock.Inlines.Add(GetHyperLink(tmp)); else textBlock.Inlines.Add(GetRunControl(tmp)); } } private static Hyperlink GetHyperLink(string uri) { if (uri.ToLower().StartsWith("www.")) uri = "http://" + uri; Hyperlink hyper = new Hyperlink(); hyper.NavigateUri = new Uri(uri); hyper.Inlines.Add(GetRunControl(uri)); return hyper; } private static Run GetRunControl(string text) { Run run = new Run(); run.Text = text + " "; return run; } private static string[] SplitSpace(string val) { string[] splittedVal = val.Split(new string[] {" "}, StringSplitOptions.None); return splittedVal; } } }
In the above code I analyze the text for urls after splitting it, you can also do it using RegEx. As this code is just for protyping, I didn’t pay much attention to the quality of it.
In the xaml page I refer this attached property as shown below.
xmlns:conv="using:Test.App.AttachedProps"
In the Textblock, bind the text via the attached property as shown below.
<TextBlock conv:HyperLinkedTextBlock.Text="{Binding TextVal}"/>
If the TextVal has any words that starts with ‘http:’ or ‘www.’ then the above Custom Attached Property will create a HyperLink other wise create a Run control and add it to the Inline collection of the TextBlock.
Happy coding…
Add LineBreaks:
private static void AddInlineControls(TextBlock textBlock, string[] splittedString)
{
for (int i = 0; i < splittedString.Length; i++)
{
string tmp = splittedString[i];
string[] s = tmp.Split('\n');
for(int j = 0; j
0)textBlock.Inlines.Add(new LineBreak());
if (s[j].ToLower().StartsWith(“http:”) || s[j].ToLower().StartsWith(“www.”))
textBlock.Inlines.Add(GetHyperLink(s[j]));
else
textBlock.Inlines.Add(GetRunControl(s[j]));
}
}
}
Jim
February 14, 2016 at 10:01 pm
Hi,
I have two problems.
1- I tried a test with the following sample sentence:
HyperLinkedTextBlock.SetText(myTextBox, “Gün geçmiyor ki teknoloji sitelerine bir yenisi eklenmesin. Mesela; http://www.teknomeknotekno.com, http://www.takinotekinotekno.net, Facebook sayfamsı şu sayfa http://www.facebook.com/teknotekinotakino, Youtube sayfamsı şu hesap http://www.youtube.com/teknotekinotakino ve Twitter hesabımsı bu sayfa http://www.twitter.com/teknotekinotakino bunlardan sadece bazıları :)”);
The following error occurred:
Exception thrown: ‘System.UriFormatException’ in SYSTEM.NI.DLL
exception: Invalid URI: The format of the URI could not be determined.
2- I want to remove the underline from the inline Hyperlinks.
How can I solve these problems?
Kind regards,
Burhan Aksendir
July 11, 2016 at 2:07 am
I haven’t done any development in WPF for quiet a long time. I dont think I can help you out, better you post the question in some forums.
Sony Arouje
July 11, 2016 at 10:39 am
Hi,
I am developing windows 10 mobile app in UWP.
I applied the code . It shows “The name “HyperLinkedTextBlock” does not exist in the namespace “using:MynameSPace”.
Help me to solve the issue
sabi
March 28, 2017 at 3:09 pm
Recheck your reference to the HyperLink text class.
Sony Arouje
March 28, 2017 at 7:00 pm