How to list fonts in WPF using markup extensions and data templates

Learn how to pull static data into WPF with XAML's x:Static markup extension. In this tip, we'll show you how to list font families, with each font's name in its own font, in WPF. This method uses markup extensions and data templates.

Dig through the .NET class libraries for a few minutes and you'll find collections (islands) of static data. For...

example, the Fonts class exposes two static properties, Fonts.SystemFontFamilies and Fonts.SystemTypefaces, which are useful for enumerating the installed fonts on the system. In this tip, I'll show you how to list font families in WPF by filling a ListBox with the FontFamilies data.

Binding to Static Data

WPF has a special markup extension for retrieving static data. Markup extensions are classes that are called by WPF at runtime to provide a way to access static properties. Any public static field or property can be used via the x:Static markup extension. For instance, the following code snippet shows a class with a static property:

class Document {
  // defines a static property or field
  public static double DocumentWidth { get; set; }

The XAML snippet to retrieve the static DocumentWidth property would be:

  <!-- assumes you have a xmlns:local declaration pointing to the 
      assembly containing the Document class -->
  <RichTextBox Width='{x:Static local:Document.DocumentWidth}' />

Binding to FontsFamily property

Now that you understand the x:Static markup extension, let's see how to bind a ListBox to a static collection.

<!-- DataContext specifies the binding source 
     for any bindable property in the ListBox or its children.
     ItemsSource specifies the source of list data
     In this example the ItemsSource is bound to the DataContext data
 <ListBox DataContext="{x:Static Fonts.SystemFontFamilies}"

ListBox showing plain fonts

As you can see from the screen shot, the ListBox is filled with the font data. This font list is serviceable, but it's also boring. You've probably seen font lists in other applications that preview the font by as showing the font name in the actual font. Data templates are the key to creating this type of UI in bound lists.

Data Templates

A data template is an alternate UI for your application data. When WPF attempts to render your data, it checks to see if there is a template available. If so, the template is expanded and applied to your data prior to rendering to the screen. In the next example, a data template is assigned to the ListBox ItemTemplate. Note that while this template is declared within the ListBox element, it could also be placed in the Window.Resources section.

        <!-- Apply a template to each Item in listbox -->
    <!-- DataTemplate is affliated with the bound data.    
    in this case the FontFamiles property-->
    <Border Padding="5"
    <StackPanel Orientation='Vertical'>
    <TextBlock VerticalAlignment='Center'>
    <!-- ContentPresenter is the placeholder in the template
    where the bound data should be rendered. 
    In this case, I'm placing it within
    this TextBlock -->
    <ContentPresenter Content="{TemplateBinding Content}" />
    <!-- use the bound data to set the FontFamily
    for this TextBlock -->
    <TextBlock FontFamily='{Binding Source}'
        Foreground='DarkGray'>ABC DEF GHI JKL MNO PQR STU VWYZ


The ListBox should now look like this:

ListBox showing WYSIWYG fonts

Walt has trained thousands of corporate developers during the last 14 years and he travels the world speaking at software conferences, and providing developer training for corporations. He writes for several IT magazines, and worked on books/videos and .NET courses for Microsoft Press. As a Wintellect consultant he is presently focused on the WPF, Surface and Silverlight APIs. Walt is also a Microsoft MVP, WPF Disciple, Silverlight Insider and author of the free Shazzam WPF Shader utility.

This was first published in May 2009



Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to: