Sony Arouje

a programmer's log

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…

Advertisements

Written by Sony Arouje

July 16, 2014 at 2:45 pm

5 Responses

Subscribe to comments with RSS.

  1. 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

  2. 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

  3. 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


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: