Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Developing WPF Applications to Choose Best FontFamily and Display String (Text) for UI Elements

0.00/5 (No votes)
25 Sep 2013 1  
In this tip we will talk about how to apply the same font style to TextBlock and Glyphs controls from code-behind.

Introduction

In this tip we will talk about how to apply same Fonts style to TextBlock and Glyphs controls from code behind. I am trying to apply the FontFamily value for both controls from code behind. So this will give you better idea about how to use fall-back value and other fonts related property. This will also explain how to bind style setter value also.

Background

If requirement is to apply the same fonts value (FontFamily, Foreground,FontSize) to all the TextBlocks in the project. Then it can simply be done by changing the value directly form XAML code. If we need it on the run time, it can be done from code behind.  

Now the second scenario is, I have two different controls Glyphs and TextBlock. Both control have different properties for font value. For example, Glyphs have FontUri property whereas TextBlock has FontFamily. Then if we try to use the same approach as we have discussed above, it will result in very lengthy code to change the fonts from code behind at run time, but the value to both property has been same.

Usually this is done by just binding the different value to both controls, e.g.,

<Glyphs Name="glyphs" FontUri="C:\WINDOWS\Fonts\Arial.TTF" FontRenderingEmSize="50"/>
<TextBlock Name="text"  FontFamily="Arial" FontSize = "50"/> 

If we want to change these properties from code behind. We have to do something like this.

glyphs.FontUri = new Uri(@"C:\WINDOWS\Fonts\Arial.TTF");
glyphs.FontRenderingEmSize = 50.0;
text.FontFamily = new FontFamily("Arial");
text.FontSize = "50"; 

One solution is to apply the style to both control and bind the setter value to the same property variable. This will reduce the lines of code and give better extensiblity and understanding.  

Using the code

Now lets start with example, Here I want to update the properties like FontUri, Fill, FontRenderingEmSize, UnicodeString for Glyphs. Similarly for TextBlock. I want to update the property values such as FontFamily, Foreground, FontSize, Text, etc. So I took the two different styles in XAML.

<Style x:Key="ModelBodyGlyphsStyle" TargetType="Glyphs">
      <Setter Property="FontUri"  Value="{Binding ModelBodyFontFamily}"></Setter>
      <Setter Property="Fill"  Value="{Binding ModelBodyColor}"></Setter>
      <Setter Property="FontRenderingEmSize" 
          Value="{Binding ModelBodyFontSize}"></Setter>
      <Setter Property="UnicodeString" 
          Value="{Binding ModelBodyText}"></Setter>
</Style>

<Style x:Key="ModelBodyTextBlockStyle" TargetType="TextBlock">
    <Setter Property="FontFamily"  Value="{Binding ModelBodyFontFamily}"></Setter>
       <Setter Property="Foreground"  Value="{Binding ModelBodyColor}"></Setter>
       <Setter Property="FontSize"  Value="{Binding ModelBodyFontSize}"></Setter>
       <Setter Property="Text" Value="{Binding ModelBodyText}"></Setter>
</Style>

And now apply this styles to the controls 

<Glyphs Name="glyphs" Style="{StaticResource ModelBodyGlyphsStyle}"  />
<TextBlock Name="text"  Style="{StaticResource ModelBodyTextBlockStyle}" />  

In the above style, I am using the binding values are ModelBodyFontFamily, ModelBodyColor, ModelBodyFontSize, ModelBodyText. These are the public properties of FontProperties class. So that, I gave DataContext of MainWindow class as object of FontProperties class in code behind. 

Let us now look at the FontProperties class: 

This class contains the four get and set properties name as ModelBodyFontFamily, ModelBodyColor, ModelBodyFontSize, ModelBodyText. And importantly implement the interface INotifyPropertyChanged for PropertyChanged event. So this is basically a model class. 

To look at the MainWindow code: 

In this I took three buttons Arial, Verdana and Times. On their click event I change the values of all properties from FontProperties class. And these values update the UI. Now here, I added another one property FallbackModelBodyFontFamily which is used for FontFamily Fallback value. 

Lets look at the one setter from TextBlock -  

<Setter Property="FontFamily"  Value="{Binding ModelBodyFontFamily}"></Setter>

So I bind two values in ModelBodyFontFamily as comma separated values then it will choose best font and apply to the controls. This is explain on MSDN with very perfect manner FontFamily. In this link they explain about fallback value with an example.  

Note: [Taken as is from MSDN]You can define a font fallback sequence in your code, which lets you define an alternate font. When you create a FontFamily object, provide multiple font family names, separated by commas, for the String parameter, such as "Comic Sans MS, Verdana". In this case, if the glyphs from the "Comic Sans MS" typeface are not available, glyphs from the "Verdana" typeface are used. If neither "Comic Sans MS" nor "Verdana" have the required glyphs, the fallback font family of the typeface is used, which is "Global User Interface" by default. 

It means that we can add multiple FontFamily for single control and the application will decide to choose the most suitable font for its Text.  

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = Fontproerties;
    }
    
    FontProperties Fontproerties = new FontProperties();
    private void Arial_Click(object sender, RoutedEventArgs e)
    // Assing Arial FontFamily
    {
        // Apply the Font body colour to Black
        Fontproerties.ModelBodyColor = "Black";
        // Apply the FontFamily to Arial for Glyphs
        Fontproerties.ModelBodyFontFamily = @"C:\WINDOWS\Fonts\Arial.TTF";
        // Apply the FontFamily to Arial for Textblock
        Fontproerties.FallbackModelBodyFontFamily = "Arial";
        //Fallback Value: 
         http://msdn.microsoft.com/en-us/ library/system.windows.media.fontfamily.aspx

        Fontproerties.ModelBodyFontFamily = Fontproerties.ModelBodyFontFamily + 
          "," + Fontproerties.FallbackModelBodyFontFamily;
        // Apply the font size to 30
        Fontproerties.ModelBodyFontSize = 30;
        // Set the display text 
        Fontproerties.ModelBodyText = "This is Arial Text";
    }
    // similarly added the events for Verdana and Times button click. 
}

Now here is one problem – I can't assign non URI value to FontUri property of Glyphs. It will throw an Exception. For Arial button click the ModelBodyFontFamily value update to (@"C:\WINDOWS\Fonts\Arial.TTF",  Arial). Fallback value Arial is not a URI so it will throw an exception. But this will be work for TextBlock. So what I did I wrote one FontFamilyConverter class which converts the ModelBodyFontFamily value to only (@"C:\WINDOWS\Fonts\Arial.TTF") for Glyphs control. So the minor change in XAML at ModelBodyGlyphsStyle style -  

<Style x:Key="ModelBodyGlyphsStyle" TargetType="Glyphs">
    <Setter Property="FontUri" 
       Value="{Binding ModelBodyFontFamily, Converter={StaticResource 
              ResourceKey=FontFamilyConverter}, ConverterParameter=Glyphs }">
    </Setter>
</Style>

And the FontFamilyConverter class is:

public class FontFamilyConverter : IValueConverter 
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string result = String.Empty;
        if (parameter.ToString().Equals("Glyphs") && value != null)
        {
            string[] words = value.ToString().Split(',');
            result = words[0];
            return result;
        }
        return @"C:\WINDOWS\Fonts\Times.TTF";
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

Currently from code behind I only changes the FontFamily values and remaining all values are same for each events.

Let us try to run the application and perform various operations to see the solution in action.

  • Click On Arial Button:
  • Click On Verdana Button:
  • Click On Times Button:

Points of Interest 

In this Tip we have talked about a way to apply same Fonts style to TextBlock and Glyphs controls from code behind. I tried to apply the FontFamily value for both controls from code behind so that this gives a better understanding about the solution approach. This can very well be implemented with MVVM pattern. 

History 

  • 23 September 2013: First version.
  • 26 September 2013: Update the screen shots with correct spelling. 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here