Click here to Skip to main content
13,863,735 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

29.6K views
1.5K downloads
13 bookmarked
Posted 2 May 2016
Licenced CPOL

Displaying HTML in a WPF RichTextBox

, 2 May 2016
Rate this:
Please Sign up or sign in to vote.
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.

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:

<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:

<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:

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)

Share

About the Author

Clifford Nelson
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.

You may also be interested in...

Comments and Discussions

 
PraiseAnother good article Pin
CapGroupAccess29-Nov-18 11:31
memberCapGroupAccess29-Nov-18 11:31 
GeneralDealing with images Pin
quadpus19-Aug-18 2:46
memberquadpus19-Aug-18 2:46 
QuestionImage doesn't show in RichText! Pin
Shahryar Hasan Nezhad20-Feb-18 5:03
memberShahryar Hasan Nezhad20-Feb-18 5:03 
QuestionEnable Hyperlink Pin
Member 1302392617-Mar-17 16:54
memberMember 1302392617-Mar-17 16:54 
AnswerRe: Enable Hyperlink Pin
Clifford Nelson1-Jan-18 18:58
mvaClifford Nelson1-Jan-18 18:58 
AnswerRe: Enable Hyperlink Pin
Clifford Nelson22-May-18 11:36
mvaClifford Nelson22-May-18 11:36 
QuestionIs there? Pin
Rahman Mahmoodi2-May-16 13:51
memberRahman Mahmoodi2-May-16 13:51 
AnswerRe: Is there? Pin
Clifford Nelson3-May-16 9:00
mvaClifford Nelson3-May-16 9: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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web06 | 2.8.190214.1 | Last Updated 2 May 2016
Article Copyright 2016 by Clifford Nelson
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid