WPFでフォントの列挙を行う方法
WPFにはフォント選択などのダイアログがありません。
で、フォント選択ダイアログを作るときなどに必要になる、WPFでのフォント一覧の列挙方法を調べてみました。
結果はこんな感じ
フォント一覧の列挙
まずは、フォントの一覧の表示からやってみます。
システムにインストールされているフォント一覧は、以下のように1行で取得することができます。
var fontList = Fonts.SystemFontFamilies;
フォント一覧をListBoxに表示するだけのサンプル
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="525" Height="350"> <Grid> <ListBox Width="200" Margin="10" HorizontalAlignment="Left" ItemsSource="{Binding FontList}"/> </Grid> </Window>
MainWindow.xaml.cs
/// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext = new MainWindowViewModel(); } }
MainWindowViewModel.cs
class MainWindowViewModel { public IEnumerable<FontFamily> FontList { get; set; } public MainWindowViewModel() { this.FontList = Fonts.SystemFontFamilies; } }
画面表示時にフォントを適用した文字列で表示
フォント名をstringで表示しただけではどんなフォントかわかりにくいので、文字列にフォントを適用して表示してみました。
以下のようなDataTemplateを適用すると、フォントを適用したTextBlockで表示できます。
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Width="525" Height="350"> <Grid> <ListBox Width="200" Margin="10" HorizontalAlignment="Left" ItemsSource="{Binding FontList}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" FontFamily="{Binding}" FontSize="16"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>
フォント名をローカライズして表示する
フォントを適用してみても、以下のように日本語のフォント名とかを見てみると、アルファベット表記で表示されてることに気付きます。
日本語のフォントだったら、是非とも日本語で表示したい!!
ということで、コンバータを使って、実行時の言語環境に応じたローカライズをしてみました。
実行時の環境に合ったフォント名称があれば、その名称を表示し、なければFontFamilyのSourceプロパティを表示しています。
この手のコンバータのCultureInfo型のプロパティを使ってローカライズする時は、以下の1文を実行してプログラムの言語設定をしておく必要があります。
this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
以下のサンプルでは、これをMainWindowのコンストラクタで実行してます。
MainWindow.xaml
<Window x:Class="WpfBaseTemplate1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseTemplate1" Title="MainWindow" Width="525" Height="350"> <Window.Resources> <local:FontFamilyToNameConverter x:Key="FontFamilyToNameConverter" /> </Window.Resources> <Grid> <ListBox Width="200" Margin="10" HorizontalAlignment="Left" ItemsSource="{Binding FontList}"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock FontFamily="{Binding}" FontSize="16" Text="{Binding Converter={StaticResource FontFamilyToNameConverter}, Mode=OneWay}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>
MainWindow.xaml.cs
/// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name); this.DataContext = new MainWindowViewModel(); } } public class FontFamilyToNameConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var v = value as FontFamily; var currentLang = XmlLanguage.GetLanguage(culture.IetfLanguageTag); return v.FamilyNames.FirstOrDefault(o => o.Key == currentLang).Value ?? v.Source; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
結果はこんな感じ。
とりあえず、表示するだけなら割と簡単にできそう。