在WPF应用程序中,经常需要为用户提供字体选择的功能。这可以通过ComboBox控件实现,它允许用户从下拉列表中选择字体。本文将介绍如何仅使用XAML来创建这样的控件,而不需要任何后台代码。
在寻找解决方案的过程中,偶然发现了Pete O'Hanlon的文章,它描述了想要实现的功能。但是,为什么还要写另一篇文章呢?因为文章的第一个评论者提出了一个建议,让想到了将两者结合起来,作为一个纯粹的XAML解决方案,可以直接复制粘贴使用。
以下是完整的XAML代码示例:
<ComboBox xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
ItemTemplate="{DynamicResource FontTemplate}">
<ComboBox.Resources>
<CollectionViewSource x:Key="myFonts"
Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
<CollectionViewSource.SortDescriptions>
<ComponentModel:SortDescription PropertyName="Source" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<Style x:Key="FontStyle">
<Setter Property="Control.FontFamily" Value="{Binding Source}" />
<Setter Property="Control.FontSize" Value="16" />
</Style>
<DataTemplate x:Key="FontTemplate">
<StackPanel VirtualizingStackPanel.IsVirtualizing="True">
<TextBlock Style="{StaticResource FontStyle}" Text="{Binding Source}" ToolTip="{Binding Source}" />
</StackPanel>
</DataTemplate>
</ComboBox.Resources>
<ComboBox.ItemsSource>
<Binding Source="{StaticResource myFonts}" />
</ComboBox.ItemsSource>
</ComboBox>
这段代码可以直接复制粘贴到项目中。然后,可以将ComboBox的SelectedValue绑定到选择的属性上。SelectedValue的类型是System.Windows.Media.FontFamily。
这段代码中有几个关键点需要解释。注意!XAML代码更加详细了!
直接跳到ComboBox.Resources部分:获取了系统字体的完整集合。但是,默认情况下,它们只是部分排序(按FamilyName),所以将它们排序到自己的集合myFonts中。通过以下XAML标记导入ComponentModel命名空间:
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
然后创建自己的按Source属性(即字体家族名称)排序的集合:
<CollectionViewSource x:Key="myFonts"
Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
<CollectionViewSource.SortDescriptions>
<ComponentModel:SortDescription PropertyName="Source" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
声明了一个简单的模板,该模板在ComboBox中以自己的字体类型呈现字体,并提供工具提示。
最后,将ComboBox.ItemsSource绑定到排序的字体集合myFonts上,使用长格式XAML绑定。
ItemsSource属性要求它绑定到一个静态资源。假设这样做:
<ComboBox xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
ItemTemplate="{DynamicResource FontTemplate}"
ItemsSource="{Binding Source={StaticResource myFonts}}">
会抛出一个异常:“找不到名为'myFonts'的资源。资源名称区分大小写。”因为myFonts还没有声明。
当然,也可以将字体集合移动到UserControl/Window/Application Resources部分,但在本例中,只有一个字体组合框,所以将其放在ComboBox.Resources部分是很好的。
如上所述,如果打算使用这个XAML(并且多次使用字体组合框),将排序的字体集合:
<CollectionViewSource x:Key="myFonts"
Source="{Binding Source={x:Static Fonts.SystemFontFamilies}}">
...
</CollectionViewSource>
xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"