Sony Arouje

a programmer's log

Posts Tagged ‘Hyperlink

WinRT TextBlock with HyperLinks

with 5 comments

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…

Written by Sony Arouje

July 16, 2014 at 2:45 pm

%d bloggers like this: