Icon Fonts in UWP Apps
Icons are an essential element for graphical user interfaces. They allow intuitive actions by users, provide space optimization (e.g. Toolbars), create better mnemonics around app’s functionality, among other things that go beyond the goal for this post. In summary, they are nice to have in our apps, but with proper use. Too much of something good leads to bad results.
Methods to load iconographic assets in apps have improved over the years. A great advantage to those who do not have the support of graphical designers on their teams. Icons for apps have evolved from old day clip-art galleries all the way to icons stored inside font files. This latest method besides being handy provides the ability to render vectorized icons. Vectors adapt themselves to different display resolutions where our app might be available. Most of the XAML visual elements are vectors and so should be icons.
Microsoft offers many fonts that ship with Windows containing illustration assets. From the traditional Wingdings fonts to the new ones designed for modern apps, the Segoe family of fonts. In the latest version of Windows 10, we can find Segoe MDL2 Assets and Segoe UI Emoji. They come preinstalled in the system and can be consumed by controls that render text simply by changing the FontFamily property of the control. Although, there are a series of controls created to display icon assets.
Icon Classes
Image 1 Character Map.
The UWP development platform provides a series of classes that extend the IconElement class, but only two of them support fonts as their source. FontIcon and SymbolIcon, these classes differ in the way we indicate what icon to use. SymbolIcon is created exclusively to consume icons from Segoe MDL2 Assets, and its source can’t be changed. It allows the class to expose a Symbol property that accepts an easy to memorize icon friendly name, as oppose to FontIcon where we can assign a different FontFamily value and indicate the icon to use through its Glyph property using the internal Unicode value representing the glyph location inside the font file.
The value we can assign to the Symbol property in a SymbolIcon does not include the valid glyphs that the font provides. For those cases, the recommended method is to use the FontIcon class instead. We can freely indicate the Unicode value based on what the font contains. The two font icons that come with Windows usually get additional icons as new versions of Windows ship. For this reason, we need to be careful in assuming that a Unicode value will render a valid icon in the previous version of Windows where our app could be running as well. Check on MSDN or use the Character Map accessory application that comes with Windows to verify a Unicode value and if it is valid in the versions of Windows the app targets.
When using a Unicode value identified in the Character Map we use one of two formats based on where we make the assignment. In XAML code we use "" where E787 is the hexadecimal value for the selected glyph in Character Map in image 1. To use it in code-behind the format is "\uE787" .
Colorizing Icons
Image 2 Overlapping icons with color.
The icons found in Segoe UI Emoji font come with color information for its glyphs. This color is shown if the platform or the application they are rendered in supports multicolor layers coming from fonts, UWP apps support it as well as Windows 10. In cases where there is no support for color, a monochromatic version of the emoji is displayed. Some text controls (TextBlock and TextBox) provide a property IsColorFontEnabled to indicate when to use color or the fallback monochromatic version. FontIcon does not have this option. The glyphs found on Segoe MDL2 Assets are only monochromatic. There is no color information coming from the font itself, but that does not prevent us from setting the control’s Foreground property to some color and get the font’s glyphs colorized. If we look closely at all the glyphs provided by this font we will notice that certain icons come in two versions: outline and filled. Having a FontIcon instance rendering the fill glyph and assigning a color to its Foreground property, and overlapping another instance of FontIcon rendering the outline version of the icon creates the effect of multiple layers with different colors.
Custom Fonts
As seen in the previous section, there are instances where the icon we are looking for is not provided by any of the system fonts or that an icon does not have its corresponding outline/fill version we wish. To solve this, we could look for other fonts available online, free or commercial, and embed them into our project. Some projects might even have the budget to get professional font designer services where we could have fonts created with icons from trademarked visual assets, like logos or other visual assets that help our app set a differentiating element.
Image 3 TrueTypeFont file embedded in project.
With a font file (usually TTF) that contains our custom icons embedded into the application project, we can proceed and use it in the different controls that we discussed earlier that support FontFamily changes. The same way as we add image files to the project we can add a font file. Verify that the file is added to the project with Build Action set to Content.
Once we have the file in the project is a matter of reference it in the FontFamily property of the control using this format:
FontFamily="[PathToTTF]#[NameOfFontFamily]"
A font file could define more than one font family, for this reason, we need to indicate its name after the file name. On code-behind you can set this property as well, FontFamily is a class that its constructor takes a string value indicating a Uri pointing to a resource. We can take this mechanism to refer to a custom font in our project this way.
string fontFilePath = “ms-appx:///Assets/Fonts/MyCustomFont.ttf#My Personal Icons”;
fontIcon.FontFamily = new FontFamily(fontFilePath);
Notice that the Uri uses the application Uri schema to refer to resources in a project. This provides the possibility to have font files embedded in satellite assemblies (Class Libraries).
string assemblyName = GetType().GetTypeInfo().Assembly.GetName().Name;
string fontFamilyPath = $"ms-appx:///{assemblyName}/Fonts/MyCustomFont.ttf#My Personal Icons");
Final thoughts
Before closing this post, let’s talk about the user licenses that govern the use of fonts. The contents of fonts, being them letters or symbols, are bound to license that indicates if it is possible or not for us to redistribute the file with our application. It also indicates other permissions or restrictions regarding the modifications of the glyphs it contains.
A graphical designer or a company might have trademarked those designs an explicit permission should exist. In the case of the Segoe fonts or other fonts that are part of Windows 10, when we refer to their glyphs in our app without embedding the file in our project is part of the expected usage of it allowed by its license. We are not distributing the font and when the application is launched in a customer’s Windows 10 machine it will load the font information from that machine.
Same goes for any other font from the internet. We need to check what permissions or restrictions we must follow to make use of it.
In summary, we visited the icon controls that the platform offers as well as how to consume the system provided icons in those controls and a mechanism to include custom-made fonts embedded in our project or a class library.