Posts Tagged ‘Hyperlink’
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…