Hyperlink columns in a WPF DataGrid

In the last couple of posts (here and here) we’ve seen how to connect to a MySQL database and use a DataGrid as a UI for editing the contents of the database. One useful feature of a DataGrid is its DataGridHyperlinkColumn, in which each cell is a hyperlink to a URL. In the Comics database, for example, we store with each comic a link to its page at the ComicVine web site.

In order for the hyperlinks in such a column to become active, we need to embed the page in a NavigationWindow or a Frame. We’ll have a look at NavigationWindow here.

The NavigationWindow works pretty much the same way as the ordinary Window. To convert an existing Window-based WPF application into one using NavigationWindow, replace the Window tag at the start and end by NavigationWindow. Also, change the Window.Resources block to NavigationWindow.Resources.

One difference, however, is that the NavigationWindow doesn’t support direct content, meaning that you can’t place a layout manager like Grid directly into a NavigationWindow. After the NavigationWindow.Resources block, you need to insert a NavigationWindow.Content block, and you can then place your root Grid layout inside that. Those are the only changes you need to make to convert to NavigationWindow.

So what does a NavigationWindow do for you? The main thing is that it provides an embedded web browser, so that when you click on a hyperlink, the web page will be displayed inside the application’s main window. You will also see ‘forward’ and ‘back’ navigation buttons at the top of the window, which work in the same way as in a regular browser, except that the original display of the DataGrid is included in the sequence of windows displayed. For example, if you start with a DataGrid containing a hyperlink and click on the hyperlink, you’ll be sent to the web page you clicked on. If you then click the ‘back’ button, you’re taken back to the DataGrid.

I haven’t explored the browser in great depth, but it appears to be a stripped-down version of Internet Explorer. It seems to be OK for displaying more web pages, but pages requiring interaction (such as the editing page at ComicVine) aren’t fully supported; the text editor on this page won’t work, and ComicVine provides a simpler notepad-like editor in its place. But for just displaying a page for the user’s information it seems fine.

One other feature of the hyperlink column is worth mentioning. By default, the column will display the text entered into a cell as a hyperlink. However, usually URLs are quite long and often don’t contain user-friendly text so it’s not obvious where the link is directing you. A better interface can be built by providing a converter that displays more user-friendly text. In the Comics example, the entry for the column is this:

   <DataGridHyperlinkColumn  Header="ComicVine" Binding="{Binding ComicVine}"
     ContentBinding="{Binding ComicVine, Converter={StaticResource ComicVineConverter}}"
     IsReadOnly="True"/>

The ‘Binding’ property binds the text that is used as the URL. By default, this is also the text that is displayed in the column’s cells. If we want the column to display different text, but still link that text to the underlying URL, we can specify a ‘ContentBinding’. In this case, we’ve bound the content to the same text as the main URL binding, but we’ve provided a converter which will change the text displayed. In a cleverer application, we might be able to extract some text from the URL to create a user-friendly label. In this case, however, we’ve just produced the constant string ‘ComicVine’ as the display content. The converter is specified in the NavigationWindow.Resources section as:

    <local:ComicVineConverter x:Key="ComicVineConverter"/>

The code behind looks like this:

  class ComicVineConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      if (value != null && value.ToString().Length > 0)
      {
        string comicVine = "ComicVine";
        return comicVine;
      }
      string empty = "";
      return empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      Uri comicVine = new Uri((string)value);
      return comicVine;
    }
  }

We could get fancy and do some string parsing on the URL, or we could pass in a parameter containing other information such as the issue’s title and number, and use these to build a label tailored to each issue. However, since all the information is already displayed on the same row in the DataGrid, this seems a bit redundant.

Advertisements
Post a comment or leave a trackback: Trackback URL.

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: