Loading rich text file links in a browser from a WPF Navigation Application

Previously, I discussed loading a rich text file in a regular WPF Application in this post.
Loading a RichTextBox from an RTF file using binding or a RichTextFile control

UPDATE: If you use the new version of RichTextFile located at this link, then you don’t even need to do this.

The following use cases must be met:

  1. Load and display a rich text file in read only mode
  2. The links must open inside a browser and not in the application

We created a RichTextFile control that inherits RichTextBox and configured it to support binding. Now we are going to use this same object in a WPF Navigation Application.

A WPF Navigation Application is going to react differently. Links are going work by default, so the Hyperlink.Click event doesn’t have to be used. However, there is a problem, the links open in the actual application’s window and not in a browser. Lets fix this.

Part 2 – Using the RichTextFile class in a WPF Navigation Application

Use Case 1 – Loading a rich text file

Create a new WPF Application in Visual Studio.

Add a Frame element and set the source to RTF.xaml, which we will create next.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" />
    </Grid>
</Window>

There is no code behind for this, yet.

Create a new WPF Page called RTF.xaml.

Add the above RichTextFile object to the project.

Add an xmlns reference to our new object. Then add our new object. Notice in our new object that we set IsReadOnly=”True” but we also set IsDocumentEnabled=”True”. This allows for clicking a link even though the document is read only.

<Page x:Class="RichTextFileTest.RTF"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="RTF"
      xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsReadOnly="True" IsDocumentEnabled="True"/>
    </Grid>
</Page>

Code Behind

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for RTF.xaml
    /// </summary>
    public partial class RTF : Page
    {
        public RTF()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

Now the first use case is complete, the rich text file is loading into the RichTextFile control and is visible in the application. However, the second use case is incomplete, but not because the links aren’t loading, but because they are not loading in a browser. Instead they are loading inside the Frame element.

Use Case 2 – Getting the links to open in a browser

Getting the links to open in a browser is not straight forward and it took me quite some time to find an easy solution. Somehow, the link must be open in a browser and then the Navigation event must be canceled.

The easiest way to do this is to implement the Nagivating function on the Frame element in our MainWindow.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" Navigating="Frame_Navigating"/>
    </Grid>
</Window>

Now implement the code behind for the Frame_Navigating method.

using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace RichTextFileTest
{
    /// <summary> 
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Frame_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            Frame frame = sender as Frame;
            if (frame != null && frame.Source != null)
            {
                // See if we are hitting a link using HTTP or HTTPS
                if (frame.Source.ToString().StartsWith("http://", System.StringComparison.CurrentCultureIgnoreCase)
                    || frame.Source.ToString().StartsWith("https://", System.StringComparison.CurrentCultureIgnoreCase))
                {
                    // Open the URL in a browser
                    Process.Start(frame.Source.ToString());

                    // Cancel the Navigation event
                    e.Cancel = true;
                }
            }
        }
    }
}

The links should now be opening in your browser and not in your application.

Here is the sample project that demonstrates this.
RichTextFileNavigation.zip

4 Comments

  1. Francisco says:

    The M' signifies the start point for the firuge, and is required. The Z' at the end of the path definition effectively closes the path, and while this isn't required to create a valid XAML firuge it is a functional requirement when generating bitmap borders since we need to generate a closed shape.

  2. Highly descriptive blog, I enjoyed that bit. Will there be a part 2?

  3. [...] Part 2 – Using the RichTextFile class in a WPF Navigation Application Category: C# (C-Sharp), WPF  |  Comment (RSS)  |  Trackback [...]

Leave a Reply

How to post code in comments?

*