Using Font Icons





5.00/5 (11 votes)
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:
FontAwesome
: http://fortawesome.github.io/Font-Awesome/
Using the Code
- Create a new WPF Project (can be MVVM).
- Create a ribbon (Add reference to
System.Windows.Controls.Ribbon
). - Embed a font that will contain scalable icons:
- From your Resource.resx, add the ttf file
- In solution explorer, find the TTF file and change the "Build action" to "Resource"
- Add reference to
WpfTools
(in download package) - Use font icons as ImageSource
To display an icon from a font:
<RibbonButton Label="Import data"
LargeImageSource="{WpfTools:ImageFromFont Text=,
FontFamily=/RibbonFontIconSample;component/Resources/#FontAwesome, Brush=Brown}" />
Use the following parameters:
Text
: The character representing the icon (depending on the font. ForFontAwesome
, 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 aColor
or astatic
resource)Style
for italicWeight
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