Click here to Skip to main content
14,304,866 members

WPF RichTextBox containing Hyperlinks

Rate this:
4.63 (5 votes)
Please Sign up or sign in to vote.
4.63 (5 votes)
21 Jan 2017CPOL
Creating a custom RichTextBox that supports Hyperlinks

Download sample

Introduction

When working with Web controls it is quite easy to add hyperlinks within a paragraph of text. But while using windows applications the same is not so straight forward. The article shows how a  WPF RichTextBox control can be modified to include hyperlinks in between normal text.

Image 1

Background

Some time back, A friend of mine was working on a Windows application which contained a lot of text content. Within the text content he needed certain words / ID's to be hyperlinks, So that a user could click on those words and navigate to a different page ( In this case a web page ) which could show more information related to the word.

When working with WPF text controls one can easily include Hyperlinks  using controls  using code similar to the Below

<TextBlock> 
    <Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">Click here
     </Hyperlink>
</TextBlock>

But this approach may not work if you need hyperlinks within sentences or paragraphs of text that are dynamically bound to the view. Similar to #hashtags.

The Solution involves creating a custom RichTextBox control that supports this functionality.

Using the code

The basic component of this solution is the CustomRichTextBox control which is created by deriving from a normal RichTextBox control. This control will have all the properties of a RichTextBox control and an additional dependency property named "CustomText" to display the text content bound to the control.

public class CustomRichTextBox : RichTextBox
    {

        #region CustomText Dependency Property

        public static readonly DependencyProperty CustomTextProperty = DependencyProperty.Register("CustomText", typeof(string), typeof(CustomRichTextBox),
       new PropertyMetadata(string.Empty, CustomTextChangedCallback), CustomTextValidateCallback);

        private static void CustomTextChangedCallback(
            DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            (obj as CustomRichTextBox).Document = GetCustomDocument(e.NewValue as string);
        }

        private static bool CustomTextValidateCallback(object value)
        {
            return value != null;
        }

        public string CustomText
        {
            get
            {
                return (string)GetValue(CustomTextProperty);
            }
            set
            {
                SetValue(CustomTextProperty, value);
            }
        } 

        #endregion


        public CustomRichTextBox()
        {

        }

        private static  FlowDocument GetCustomDocument(string Text)
        {
            FlowDocument document = new FlowDocument();
            Paragraph para = new Paragraph();
            para.Margin = new Thickness(0); // remove indent between paragraphs
            foreach (string word in Text.Split(' ').ToList())
            {
                //This condition could be replaced by the Regex
                if(word.StartsWith("#"))
                {
                    string linkName = word.Substring(1, word.Length - 1);
                    //linkURL can be changed based on some condition.
                    string linkURL = GetUrl(linkName);
                   

                    Hyperlink link = new Hyperlink();
                    link.IsEnabled = true;
                    link.Inlines.Add(linkName);
                    link.NavigateUri = new Uri(linkURL);
                    link.RequestNavigate += (sender, args) => Process.Start(args.Uri.ToString());
                    para.Inlines.Add(link);
                }
                else
                {
                    para.Inlines.Add(word);
                }
                para.Inlines.Add(" ");
            }
            document.Blocks.Add(para);
            return document;
        }

        //This method may contain any logic to return a Url based on a key string
        static string GetUrl(string key)
        {
            return string.Format(@"https://www.google.com/#q={0}", key);
        }

    }

The method GetCustomDocument(string Text) splits each word in the text bound to the control and if a '#' prefix is encountered in a word, it dynamically creates a Hyperlink and adds it to the flow document.

Once the CustomRichTextBox control is ready it can used in a view (xaml) and bound to a property with text content just as you would bind content with a text control.

<local:CustomRichTextBox IsDocumentEnabled="True" IsReadOnly="True" CustomText="{Binding Details}" /> 

And That's it ..

For an input text below :

"Lorem Ipsum has been the industry's standard dummy #Ford text ever since the 1500s."

The control would display the text as follows

Image 2

A full usage of this control in a simple WPF application is illustrated in the project attached with this article. So you can download the code to see the control in action.

Points of Interest

I have kept the article and the sample project as simple as possible so that it can be easily understood and modified by a person even though new to WPF. The approach can be used to include controls other than Hyperlinks as well.

For those new to WPF here are few topics you should become familiar with once you understand the article and the code.

  • Overiew of a RichTextBox control
  • Creating WPF Custom Controls
  • Adding & using Dependency Properties
  • Usage of Data Templates
  • Simple MVVM Binding

History

Initial Version : 18 January 2017

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Aaron Francis Dias
Software Developer (Senior)
India India
A Computer Science Graduate with 8+ Years experience in developing Windows and Web based applications using the .Net platform.
Microsoft Certified Technology Specialist (MCTS) - Windows Applications

Comments and Discussions

 
QuestionPossible to include tab in above Pin
vbinay9-May-17 21:26
membervbinay9-May-17 21:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 17 Jan 2017

Stats

10.2K views
272 downloads
6 bookmarked