Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / WPF

Displaying HTML in a WPF RichTextBox

Rate me:
Please Sign up or sign in to vote.
4.92/5 (14 votes)
2 May 2016CPOL2 min read 76.4K   3.2K   14   20
Presents code to display bindable HTML text in a WPF RichTextBox or a WebBrowser.

Introduction

I recently had need to display part of some bound read-only text with some of the text bolded. I could have used multiple controls, but that would reduce maintainability. I wanted to use HTML because that is well understood by many people, and it seemed like it would be useful in other situations.

The RichTextBox Design

I used a behavior to do this, but it could have been class derived from the RichTextBox.

C#
public class HtmlRichTextBoxBehavior : DependencyObject
{
 public static readonly DependencyProperty TextProperty =
   DependencyProperty.RegisterAttached("Text", typeof(string),
   typeof(HtmlRichTextBoxBehavior), new UIPropertyMetadata(null, OnValueChanged));

 public static string GetText(RichTextBox o) { return (string)o.GetValue(TextProperty); }

 public static void SetText(RichTextBox o, string value) { o.SetValue(TextProperty, value); }

 private static void OnValueChanged(DependencyObject dependencyObject,
   DependencyPropertyChangedEventArgs e)
 {
  var richTextBox = (RichTextBox)dependencyObject;
  var text = (e.NewValue ?? string.Empty).ToString();
  var xaml = HtmlToXamlConverter.ConvertHtmlToXaml(text, true);
  var flowDocument = XamlReader.Parse(xaml) as FlowDocument;
  HyperlinksSubscriptions(flowDocument);
  richTextBox.Document = flowDocument;
 }

 private static void HyperlinksSubscriptions(FlowDocument flowDocument)
 {
  if (flowDocument == null) return;
  GetVisualChildren(flowDocument).OfType<Hyperlink>().ToList()
           .ForEach(i => i.RequestNavigate += HyperlinkNavigate);
 }

 private static IEnumerable<DependencyObject> GetVisualChildren(DependencyObject root)
 {
  foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
  {
   yield return child;
   foreach (var descendants in GetVisualChildren(child)) yield return descendants;
  }
 }

 private static void HyperlinkNavigate(object sender,
  System.Windows.Navigation.RequestNavigateEventArgs e)
 {
  Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
  e.Handled = true;
 }
}

This code depends on code that is available from Microsoft; the HtmlToXamlConverter. All this Microsoft code is included in the folder HtmlConverter in the sample project.

Using the Behavior with a RichTextBox

The most straight forward way to use the behavior is as follows:

XML
<RichTextBox Grid.Row="1"
             local:HtmlRichTextBoxBehavior.Text="{Binding Text}" />

You could have some unintended issues with this because you can still edit the RichTextBox. There are a few other issues also. To fix at least most of these issues I did the following:

XML
<RichTextBox Background="Transparent"
             BorderThickness="0"
             behaviors:RichTextBoxHelper.Text="{Binding Name}"
             IsDocumentEnabled="True"
             IsReadOnly="True" />

This makes the RichTextBox look a lot more like a TextBox. The IsDocumentEnabled="True" is required to enable the hyperlinks. the IsReadOnly="True" ensures that the content cannot be changed. 

The WebBrowser Design

Used a behavior also for binding a string containing the HTML to the contents of a WebBrowser:

C#
public class WebBrowserBehavior
{
 public static readonly DependencyProperty BodyProperty =
   DependencyProperty.RegisterAttached("Body", typeof(string), typeof(WebBrowserBehavior),
    new PropertyMetadata(OnChanged));

 public static string GetBody(DependencyObject dependencyObject)
 {
  return (string)dependencyObject.GetValue(BodyProperty);
 }

 public static void SetBody(DependencyObject dependencyObject, string body)
 {
  dependencyObject.SetValue(BodyProperty, body);
 }

 private static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) =>
  ((WebBrowser)d).NavigateToString((string)e.NewValue);
}

This is about a simple a behavior as can be created

Using the Behavior with a WebBrowser

The most straight forward way to use the behavior is as follows:

<WebBrowser local:WebBrowserBehavior.Body="{Binding Text}" />

Points of Interest

Right now the Hyperlinks do not work for the RichTextBox. Apparently this is an issue with the WPF RichTextBox. If something similar is done with the WinForm RichTextBox, "DetectUrls="True"" will enable Hyperlinks.

When a Hyperlink is clicked in the WebBrowser control, the URI is immediately opened. This may not be particularly desirable, so may want to disable it.

One of the advantages of using the RichTextBox is that the behavior can be updated to do a conversion back. Actually some of the key strokes work in the RichTextBox so that you can bold an entry with the "ctrl + b" keystrokes. I did not create the ability to convert back, but would be an easy task.

History

  • 05/02/2016: Initial version.
  • 05/03/2016: Added WebBrowser version to sample

License

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


Written By
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
QuestionCall back from the richtextbox Pin
suresh9sb11-Feb-21 16:33
suresh9sb11-Feb-21 16:33 
AnswerRe: Call back from the richtextbox Pin
Clifford Nelson24-May-22 8:35
Clifford Nelson24-May-22 8:35 
QuestionUnder line and Through line not working ? Pin
Hard Gaming19-Oct-20 0:21
Hard Gaming19-Oct-20 0:21 
AnswerRe: Under line and Through line not working ? Pin
Hard Gaming19-Oct-20 8:04
Hard Gaming19-Oct-20 8:04 
Nevermind i made it work. Smile | :) .. Thanks for this implementation. I updated the parser as per my requirements. Great Work.Thumbs Up | :thumbsup: Java | [Coffee]
AnswerRe: Under line and Through line not working ? Pin
Clifford Nelson24-May-22 8:36
Clifford Nelson24-May-22 8:36 
QuestionAdding the Binding Code Pin
Niloshima Srivastava28-Jun-19 8:56
Niloshima Srivastava28-Jun-19 8:56 
AnswerRe: Adding the Binding Code Pin
Clifford Nelson24-May-22 8:37
Clifford Nelson24-May-22 8:37 
QuestionHow do you add a new line in the richtextbox? Pin
Abhijith Harapanahalli20-Feb-19 4:16
Abhijith Harapanahalli20-Feb-19 4:16 
AnswerRe: How do you add a new line in the richtextbox? Pin
Stridemann14-Jun-20 3:20
Stridemann14-Jun-20 3:20 
AnswerRe: How do you add a new line in the richtextbox? Pin
Clifford Nelson24-May-22 8:39
Clifford Nelson24-May-22 8:39 
AnswerRe: How do you add a new line in the richtextbox? Pin
Clifford Nelson24-May-22 8:38
Clifford Nelson24-May-22 8:38 
PraiseAnother good article Pin
CapGroupAccess29-Nov-18 10:31
CapGroupAccess29-Nov-18 10:31 
GeneralDealing with images Pin
quadpus19-Aug-18 1:46
quadpus19-Aug-18 1:46 
QuestionImage doesn't show in RichText! Pin
Shahryar Hasan Nezhad20-Feb-18 4:03
Shahryar Hasan Nezhad20-Feb-18 4:03 
AnswerRe: Image doesn't show in RichText! Pin
Clifford Nelson24-May-22 8:40
Clifford Nelson24-May-22 8:40 
QuestionEnable Hyperlink Pin
Member 1302392617-Mar-17 15:54
Member 1302392617-Mar-17 15:54 
AnswerRe: Enable Hyperlink Pin
Clifford Nelson1-Jan-18 17:58
Clifford Nelson1-Jan-18 17:58 
AnswerRe: Enable Hyperlink Pin
Clifford Nelson22-May-18 10:36
Clifford Nelson22-May-18 10:36 
QuestionIs there? Pin
Rahman Mahmoodi2-May-16 12:51
Rahman Mahmoodi2-May-16 12:51 
AnswerRe: Is there? Pin
Clifford Nelson3-May-16 8:00
Clifford Nelson3-May-16 8:00 

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.