Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

A FontFamily ComboBox in WPF 4.5

Pete Brown - 28 March 2012

I'm working on a little WPF 4.5 sample app. As part of that, I needed to create a drop-down list of Font Families. Here's what the ComboBox currently looks like:

image

The Data Source

I wanted control over the fonts including sorting and, potentially, filtering the results. I didn't want to use static binding from XAML. So, in my viewmodel, I added a collection of FontFamily objects which is loaded by a LoadSystemFonts function.

private ObservableCollection<FontFamily> _systemFonts = new ObservableCollection<FontFamily>();
public ObservableCollection<FontFamily> SystemFonts
{
get { return _systemFonts; }
}

public void LoadSystemFonts()
{
_systemFonts.Clear();

var fonts = Fonts.SystemFontFamilies.OrderBy(f => f.ToString());

foreach (var f in fonts)
_systemFonts.Add(f);
}

I'm not yet doing any filtering here, but I could. Your own application may have similar requirements.

Virtualizing for Performance

I have more than a few fonts on my system -- most of us do. Rendering out individual lines of a ComboBox each with its own font is a bit taxing. So, if you want a ComboBox that will open without an annoying lag, you need to virtualize the list it uses. This is done by adding an ItemsPanelTemplate which uses the VirtualizingStackPanel panel as shown in this markup:

<ComboBox x:Name="FontFamilySelector"
ItemsSource="{Binding SystemFonts}"
HorizontalAlignment="Left"
Margin="20,187,0,0"
VerticalAlignment="Top"
Width="255">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Width="450" />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid Height="24">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock Grid.Column="0"
VerticalAlignment="Center"
Margin="3"
Text="{Binding}" />
<TextBlock Grid.Column="1"
Margin="3"
VerticalAlignment="Center"
Text="ABCabc123!@#$"
FontFamily="{Binding}" />

</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

In order to use Virtualization in this case, I had to set a hard-coded width on the VirtualizingStackpanel. If you try to size based on content, the panel will resize wildly as items are rendered. Virtualization means layout is deferred for items, so anything relying on up-front calculations (like "Auto" sizing in a Grid) will not behave as expected.

Note also how, because I'm binding to a WPF FontFamily object, I'm able to set the FontFamily on the TextBlock to simply {Binding} in order to get it to render in the current font.

Smooth Scrolling and Item Clipping in WPF 4.5

By default, the scrolling unit of the VirtualizingStackPanel is going to be the whole unit. That is, you won't have partial items displayed and won't have smooth scrolling. WPF 4.5 adds the ability to control this so you can now set the scroll unit to be Pixel or Item by using the VirtualizingPanel.ScrollUnit attached property on the ComboBox. This provides some refinement to the UI by making the scrolling smoother, and by allowing items to be partially clipped at the top and bottom.

image

It may not seem like much, but scolling by pixels rather than units makes the scrolling more of a "scrolling" visual as opposed to an "item swapping" visual. The effect is subtle but can be important, especially in cases where the items in the drop-down list are all similar.

Final Version

The final version of this code will be included in the small WPF 4.5 sample application. However, as you can see here, it's pretty simple to create a good font drop-down in WPF.

       
posted by Pete Brown on Wednesday, March 28, 2012
filed under:        

8 comments for “A FontFamily ComboBox in WPF 4.5”

  1. Shimmysays:
    Does anyone care about WPF and Silverlight at all?
    I am thinking about leaving out these products I loved so much and start thinking about Java or other technologies (or at least ASP.NET), that although will be far less fun I had with XAML, won't disappear from the map, which is based on my understanding what's going to happen to Silverlight in the near future, and that's according to MSFT's statements and rumors around.
    Correct me if I'm wrong, I hope I am. I love XAML, love data binding, love WCF RIA, can't go anywhere else. Hope it doesn't betray me so I don't have to leave it and seek for more consistent technologies (HTML5+JS - WTF, gimme a break).
  2. Petesays:
    @Shimmy

    Yes. There are LOADS of WPF and Silverlight applications out there today, both newly created as well as existing ones being maintained.

    Nothing's "disappearing". WPF 4.5 is in the latest .NET framework, which *isn't even released yet*. Silverlight 5 was released in December with a *10* year support policy.

    Is Silverlight the future of public web sites? No. Clearly HTML5 is winning that.
    Is Silverlight the future of tablet applications? No. Windows has WinRT XAML which looks a *lot* like Silverlight, but isn't exactly Silverlight. Your skills transfer as does much of your code.

    Visual Studio 11 includes templates for Silverlight and WPF applications for the desktop.

    Moving to Java is a bit drastic, but you need to go where your conscience leads you. Just make sure you're making an informed decision, not just getting caught up in the hype.

    Pete
  3. Stonesays:
    @Pete: Totally agree!

    Windows 8 is nice - no question. But I start to think about if Metro and so WinRT is only a current hype. Maybe in Wiindows 10, Metro is going to fill the part like Silverlight fits in Win8 today - but who knows.
    What I totally disklike is that Microsoft seems to forget the """old""" technologies. For example, yesterday I read a blog post of Microsoft on how to integrate DirectX in Metro - new concepts that I want in WPF, too.
    It seems, that I'm not the only one who think in this direction - see the comments:
    http://blogs.msdn.com/b/windowsappdev/archive/2012/03/15/combining-xaml-and-directx.aspx

    OK - but back to your article:
    A little question: Is this sample app part of the book you're writing at the moment ("Windows 8 XAML in Action") ?
    I think not (?) - so it would be nice to know in which part of your projects this sample app fits... 8-)

    Stone
  4. Yiannissays:
    So Pete,

    Does Ms abandon Silverlight, because for LOB apps it is tons better than WinRT (doesn't even have a date time picker) and HTML 5 for intranet?

    Can we at least get async support for SL5+

    Such a petty that Ms killes SL. It is not the runs everywhere scenarios but for LOBs it is very good.
  5. Rod Macsays:
    The FontFamily combo is definitely very useful so good article. I just wish MS would make it clear where we are going with desktop stuff in general i.e. whether WinRT will eventually be expanded to take up the full power of WPF. So far I'm not hearing this and so I am going down the ASP.NET route which is definitely going to reduce productivity.
  6. Petesays:
    @Rod

    Why would you go ASP.NET in that case? I can't see any logical reason for that. ASP.NET isn't going to have any more desktop access than any other WinRT app.

    Also, if you are an enterprise, you can use enterprise side loading with WinRT and thereby potentially gain access to quite a bit more than the more heavily sandboxed store apps.

    Pete
  7. Rod Macsays:
    The reason for going ASP.NET would be to *ABANDON* Windows desktop development (I guess Metro consumable javascript could be a future extension/development but that seems like a kludge).

    Are you saying there is a more extensive API available to sideloaded WinRT apps, and if so, do you know where I could find a published comparison of the two schema?

    Thanks Pete.
  8. codeninjasays:
    As long as WPF is around and hopefully will be improved such as adding DirectX support to it like WinRT will have to give it feature parity, I'd be happy. Honestly, I don't mind Silverlight going away as in spirit it's in WinRT, but I never really used Silverlight nor care much about deploying in a browser (whether via SL or HTML/JS). Adding contracts to allow apps to communicate better in WPF/desktop would also be welcome.

Comment on this Post

Remember me