Click here to Skip to main content
Click here to Skip to main content

Using Font Icons

, 12 Aug 2013
Rate this:
Please Sign up or sign in to vote.
This tip helps in using font icons as ImageSource.

Introduction

This tip gives a solution to use font icons in most of WPF controls (like Ribbon).

Background

I recently worked on using a ribbon in a WPF application. The problem is that the ribbon only permits to use ImageSource to display icons. My aim is to use a font icon library (like in HTML) because it contains vector icons and the final application is homogeneous.

In the sample, you will find the Font:

Using the Code

  1. Create a new WPF Project (can be MVVM).
  2. Create a ribbon (Add reference to System.Windows.Controls.Ribbon).
  3. Embed a font that will contain scalable icons:
    1. From your Resource.resx, add the ttf file
    2. In solution explorer, find the TTF file and change the "Build action" to "Resource"
  4. Add reference to WpfTools (in download package)
  5. Use font icons as ImageSource

To display an icon from a font:

<RibbonButton Label="Import data" 
  LargeImageSource="{WpfTools:ImageFromFont Text=&#xf01a;, 
  FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}" /> 

Use the following parameters:

  • Text: The character representing the icon (depending on the font. For FontAwesome, I used the CheatSheet http://fortawesome.github.io/Font-Awesome/cheatsheet/ to get code.
  • FontFamily to choose the embedded font (use the syntax below)
  • Brush used to colorize icon (can be a Color or a static resource)
  • Style for italic
  • Weight for bold

Points of Interest

This class can be used with any controls which have an ImageSource property (Ribbon, Image, ...).

It is a way to have high definition icons in application because they are scalable vector icons.

How It Works

As you cannot override ImageSource one of the solutions is to create a MarkupExtension.

A markup extension is a class that can be used in XAML code inside { } and as only one pure abstract method ProvideValue which is called to get the resulting object.

public override object ProvideValue(IServiceProvider serviceProvider)
{
    return CreateGlyph(Text, FontFamily, Style, Weight, Stretch, Brush);
}   

In WPF, one way to render a string as a drawable object is to use Glyph (and GlyphRun).

A glyph is a way to render one or more characters in a scalar way. It uses a Font and character index to draw one letter or icon.

Here is the code that draws a text into ImageSource:

private static ImageSource CreateGlyph(string text, 
        FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, 
        FontStretch fontStretch, Brush foreBrush)
{
    if (fontFamily != null && !String.IsNullOrEmpty(text))
    {
        Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
        GlyphTypeface glyphTypeface;
        if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                throw new InvalidOperationException("No glyphtypeface found");

        ushort[] glyphIndexes = new ushort[text.Length];
        double[] advanceWidths = new double[text.Length];
        for (int n = 0; n < text.Length; n++)
        {
            ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];
            glyphIndexes[n] = glyphIndex;
            double width = glyphTypeface.AdvanceWidths[glyphIndex] * 1.0;
            advanceWidths[n] = width;
        }

        GlyphRun gr = new GlyphRun(glyphTypeface, 0, false, 1.0, glyphIndexes,
                                    new Point(0, 0), advanceWidths, 
                                    null, null, null, null, null, null);
        GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(foreBrush, gr);
        return new DrawingImage(glyphRunDrawing);

    }
    return null;
}

Limitations

All the properties (Text, FontFamily, Brush) are not bindable (due to MarkupExtension which is not a DependencyObject).

The size is not directly managed, because the glyph is rendered to stretch in the container object.

You have to put the class in a separate assembly (like WpfTool) to make it work in design mode (it is a known bug of Visual Studio).

History

  • 08/2013: First version

License

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

About the Author

Le Sourcier
Software Developer ECT Industries
France France
I am software engineer and I work for the aviation.
 
I'm currently working on many different project and in many different languages
- Visual C++ 6
- C#
- ASP.NET
- C and assembly
 
Have lot of fun

Comments and Discussions

 
QuestionExtensible for hover trigger/event? PinmemberMember 874244212-Dec-13 11:13 
GeneralMy vote of 5 Pinprofessionalketan italiya12-Aug-13 21:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 13 Aug 2013
Article Copyright 2013 by Le Sourcier
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid