WPF 自定义字体选择器

今天我们做一个字体选择器。

WPF 自定义字体选择器_第1张图片

先上一个设计图。

FontDialog.xaml. 这里省略头部分。直接上核心代码部分。

<Grid Margin="11">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        Grid.RowDefinitions>
        <fontChooser:FontChooser x:Name="FontChooser"
                              Grid.Row="0"
                              Margin="0,0,0,11" />
        <StackPanel Grid.Row="1"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Bottom"
                    Orientation="Horizontal">
            <Button Name="ButtonOk"
                    MinWidth="75"
                    Margin="0,0,7,0"
                    Click="OnOkClick"
                    Content="_OK"
                    IsDefault="True" />
            <Button Name="ButtonCancel"
                    MinWidth="75"
                    Click="OnCancelClick"
                    Content="_Cancel"
                    IsCancel="True" />
        StackPanel>
    Grid>
public partial class FontDialog
{
     public FontChooser Chooser
     {
         get { return FontChooser; }
     }


     public FontDialog()
     {
         InitializeComponent();
     }


     private void OnOkClick(object sender, RoutedEventArgs eventArgs)
     {
         eventArgs.Handled = true;
         DialogResult = true;
         Hide();
     }


     private void OnCancelClick(object sender, RoutedEventArgs eventArgs)
     {
         eventArgs.Handled = true;
         DialogResult = false;
         Hide();
     }
 }

开始制作允许用户选择字体的控件

FontChooser.cs. 首先继承Control并且我们需要标识模块化部件的类型这里还会用到TemplatePart特性。

 [TemplatePart(Name = "PART_FontFamilyTextBox", Type = typeof(TextBox))]
 [TemplatePart(Name = "PART_FontFamilyListBox", Type = typeof(ListBox))]
 [TemplatePart(Name = "PART_SizeTextBox", Type = typeof(TextBox))]
 [TemplatePart(Name = "PART_SizeListBox", Type = typeof(ListBox))]
 [TemplatePart(Name = "PART_TypefaceListBox", Type = typeof(ListBox))]
 [TemplatePart(Name = "PART_UnderlineCheckBox", Type = typeof(CheckBox))]
 [TemplatePart(Name = "PART_BaselineCheckBox", Type = typeof(CheckBox))]
 [TemplatePart(Name = "PART_OverlineCheckBox", Type = typeof(CheckBox))]
 [TemplatePart(Name = "PART_StrikethroughCheckBox", Type = typeof(CheckBox))]
 public class FontChooser : Control
 {
     //--------------------------------------------------------------
     #region Fields
     //--------------------------------------------------------------

     private TextBox _fontFamilyTextBox;
     private ListBox _fontFamilyListBox;
     private TextBox _fontSizeTextBox;
     private ListBox _fontSizeListBox;
     private ListBox _typefaceListBox;
     private CheckBox _underlineCheckBox;
     private CheckBox _overlineCheckBox;
     private CheckBox _baselineCheckBox;
     private CheckBox _strikethroughCheckBox;

     private bool _isInternalUpdate;   // 如果UI更新(例如复选框更改)是由代码引起的,则为true。
     private BackgroundWorker _backgroundWorker;
     #endregion


     //--------------------------------------------------------------
     #region Properties & Events
     //--------------------------------------------------------------
     #endregion


     //--------------------------------------------------------------
     #region Dependency Properties & Routed Events
     //--------------------------------------------------------------

     private static readonly DependencyPropertyKey IsLoadingPropertyKey = DependencyProperty.RegisterReadOnly(
         "IsLoading",
         typeof(bool),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(Boxed.BooleanFalse));

     public static readonly DependencyProperty IsLoadingProperty = IsLoadingPropertyKey.DependencyProperty;

     /// 
     /// 控件是否正忙于加载字体
     /// 
     /// 
     /// 字体列表构建在后台线程中。 在后台线程完成之前,包含所有字体系列的列表框为空。 
     /// 属性 IsLoading 表示后台线程是否忙于收集所有字体。 
     /// IsLoading 通常在控件模板中用于显示“正在加载...”动画,而其值为 true
     /// 
     [Browsable(false)]
     public bool IsLoading
     {
         get { return (bool)GetValue(IsLoadingProperty); }
         private set { SetValue(IsLoadingPropertyKey, Boxed.Get(value)); }
     }


     public static readonly DependencyProperty FontFamiliesProperty = DependencyProperty.Register(
         "FontFamilies",
         typeof(ICollection<FontFamily>),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(null, (d, e) => ((FontChooser)d).OnFontFamiliesChanged()));

     /// 
     /// 获取或设置用户可以选择的字体系列。 这是一个依赖属性。
     /// 
     [Description("获取或设置用户可以选择的字体系列.")]
     [Category(Categories.Default)]
     public ICollection<FontFamily> FontFamilies
     {
         get { return (ICollection<FontFamily>)GetValue(FontFamiliesProperty); }
         set { SetValue(FontFamiliesProperty, value); }
     }

     public static readonly DependencyProperty PreviewTextProperty = DependencyProperty.Register(
         "PreviewText",
         typeof(string),
         typeof(FontChooser),
         new FrameworkPropertyMetadata("The quick brown fox jumps over the lazy dog."));

     /// 
     /// 获取或设置预览框的文本
     /// 这是一个依赖属性
     /// 
     [Description("获取或设置预览框的文本.")]
     [Category(Categories.Default)]
     public string PreviewText
     {
         get { return (string)GetValue(PreviewTextProperty); }
         set { SetValue(PreviewTextProperty, value); }
     }


     public static readonly DependencyProperty SelectedFontFamilyProperty = DependencyProperty.Register(
       "SelectedFontFamily",
       typeof(FontFamily),
       typeof(FontChooser),
       new FrameworkPropertyMetadata(TextBlock.FontFamilyProperty.DefaultMetadata.DefaultValue,
                                     (d, e) => ((FontChooser)d).OnSelectedFontFamilyChanged()));

     /// 
     /// 获取或设置选定的字体系列
     /// 这是一个依赖属性
     /// 
     [Description("获取或设置选定的字体系列.")]
     [Category(Categories.Default)]
     public FontFamily SelectedFontFamily
     {
         get { return (FontFamily)GetValue(SelectedFontFamilyProperty); }
         set { SetValue(SelectedFontFamilyProperty, value); }
     }


     public static readonly DependencyProperty SelectedFontSizeProperty = DependencyProperty.Register(
         "SelectedFontSize",
         typeof(double),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(TextBlock.FontSizeProperty.DefaultMetadata.DefaultValue,
                                       (d, e) => ((FontChooser)d).OnSelectedFontSizeChanged()));

     /// 
     /// 获取或设置选定的字体大小(以像素为单位)(px)。 这是一个依赖属性
     /// 
     [Description("获取或设置选定的字体大小(以像素为单位)(px).")]
     [Category(Categories.Default)]
     public double SelectedFontSize
     {
         get { return (double)GetValue(SelectedFontSizeProperty); }
         set { SetValue(SelectedFontSizeProperty, value); }
     }


     public static readonly DependencyProperty SelectedFontStretchProperty = DependencyProperty.Register(
         "SelectedFontStretch",
         typeof(FontStretch),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(TextBlock.FontStretchProperty.DefaultMetadata.DefaultValue,
                                       (d, e) => ((FontChooser)d).OnSelectedTypefaceChanged()));

     /// 
     /// 获取或设置选定的字体拉伸。
     /// 这是一个依赖属性
     /// 
     [Description("获取或设置选定的字体拉伸.")]
     [Category(Categories.Default)]
     public FontStretch SelectedFontStretch
     {
         get { return (FontStretch)GetValue(SelectedFontStretchProperty); }
         set { SetValue(SelectedFontStretchProperty, value); }
     }

     public static readonly DependencyProperty SelectedFontStyleProperty = DependencyProperty.Register(
         "SelectedFontStyle",
         typeof(FontStyle),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(TextBlock.FontStyleProperty.DefaultMetadata.DefaultValue,
                                       (d, e) => ((FontChooser)d).OnSelectedTypefaceChanged()));

     /// 
     /// 获取或设置选定的字体样式。
	 /// 这是一个依赖属性
     /// 
     [Description("获取或设置选定的字体样式.")]
     [Category(Categories.Default)]
     public FontStyle SelectedFontStyle
     {
         get { return (FontStyle)GetValue(SelectedFontStyleProperty); }
         set { SetValue(SelectedFontStyleProperty, value); }
     }


     public static readonly DependencyProperty SelectedFontWeightProperty = DependencyProperty.Register(
         "SelectedFontWeight",
         typeof(FontWeight),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(TextBlock.FontWeightProperty.DefaultMetadata.DefaultValue,
                                       (d, e) => ((FontChooser)d).OnSelectedTypefaceChanged()));


     /// 
     /// 获取或设置选定的字体粗细。
	 /// 这是一个依赖属性。
     /// 
     [Description("获取或设置选定的字体粗细.")]
     [Category(Categories.Default)]
     public FontWeight SelectedFontWeight
     {
         get { return (FontWeight)GetValue(SelectedFontWeightProperty); }
         set { SetValue(SelectedFontWeightProperty, value); }
     }


     public static readonly DependencyProperty SelectedTextDecorationsProperty = DependencyProperty.Register(
         "SelectedTextDecorations",
         typeof(TextDecorationCollection),
         typeof(FontChooser),
         new FrameworkPropertyMetadata(TextBlock.TextDecorationsProperty.DefaultMetadata.DefaultValue,
                                       (d, e) => ((FontChooser)d).OnSelectedTextDecorationsChanged()));

     /// 
     /// 获取或设置选定的文本装饰。
     /// 这是一个依赖属性
     /// 
     [Description("获取或设置选定的文本装饰.")]
     [Category(Categories.Default)]
     public TextDecorationCollection SelectedTextDecorations
     {
         get { return (TextDecorationCollection)GetValue(SelectedTextDecorationsProperty); }
         set { SetValue(SelectedTextDecorationsProperty, value); }
     }
     #endregion


     //--------------------------------------------------------------
     #region Creation & Cleanup
     //--------------------------------------------------------------

     static FontChooser()
     {
         DefaultStyleKeyProperty.OverrideMetadata(typeof(FontChooser), new FrameworkPropertyMetadata(typeof(FontChooser)));
     }


     public FontChooser()
     {
         FontFamilies = Fonts.SystemFontFamilies;
         Loaded += OnLoaded;
         Unloaded += OnUnloaded;
     }
     #endregion


     //--------------------------------------------------------------
     #region Methods
     //--------------------------------------------------------------

     /// 
     /// 在派生类中重写时,只要应用程序代码或内部调用 FrameworkElement.ApplyTemplate
     /// 
     public override void OnApplyTemplate()
     {
         // ----- Clean up.
         if (_fontFamilyListBox != null)
         {
             _fontFamilyTextBox.TextChanged -= OnFontFamilyTextBoxTextChanged;
             _fontFamilyTextBox.LostFocus -= OnFontFamilyTextBoxLostFocus;
             _fontFamilyListBox.SelectionChanged -= OnFontFamilyListBoxSelectionChanged;
             _fontSizeTextBox.TextChanged -= OnFontSizeTextBoxTextChanged;
             _fontSizeListBox.SelectionChanged -= OnFontSizeListBoxSelectionChanged;
             _typefaceListBox.SelectionChanged -= OnTypefaceListBoxSelectionChanged;
             _underlineCheckBox.Checked -= OnTextDecorationCheckBoxChanged;
             _underlineCheckBox.Unchecked -= OnTextDecorationCheckBoxChanged;
             _baselineCheckBox.Checked -= OnTextDecorationCheckBoxChanged;
             _baselineCheckBox.Unchecked -= OnTextDecorationCheckBoxChanged;
             _strikethroughCheckBox.Checked -= OnTextDecorationCheckBoxChanged;
             _strikethroughCheckBox.Unchecked -= OnTextDecorationCheckBoxChanged;
             _overlineCheckBox.Checked -= OnTextDecorationCheckBoxChanged;
             _overlineCheckBox.Unchecked -= OnTextDecorationCheckBoxChanged;

             _fontFamilyTextBox = null;
             _fontFamilyListBox = null;
             _fontSizeTextBox = null;
             _fontSizeListBox = null;
             _typefaceListBox = null;
             _underlineCheckBox = null;
             _baselineCheckBox = null;
             _strikethroughCheckBox = null;
             _overlineCheckBox = null;
         }

         base.OnApplyTemplate();

         // ----- Get template parts.
         _fontFamilyTextBox = GetTemplateChild("PART_FontFamilyTextBox") as TextBox ?? new TextBox();
         _fontFamilyListBox = GetTemplateChild("PART_FontFamilyListBox") as ListBox ?? new ListBox();
         _fontSizeTextBox = GetTemplateChild("PART_SizeTextBox") as TextBox ?? new TextBox();
         _fontSizeListBox = GetTemplateChild("PART_SizeListBox") as ListBox ?? new ListBox();
         _typefaceListBox = GetTemplateChild("PART_TypefaceListBox") as ListBox ?? new ListBox();
         _underlineCheckBox = GetTemplateChild("PART_UnderlineCheckBox") as CheckBox ?? new CheckBox();
         _baselineCheckBox = GetTemplateChild("PART_BaselineCheckBox") as CheckBox ?? new CheckBox();
         _strikethroughCheckBox = GetTemplateChild("PART_StrikethroughCheckBox") as CheckBox ?? new CheckBox();
         _overlineCheckBox = GetTemplateChild("PART_OverlineCheckBox") as CheckBox ?? new CheckBox();

         // ----- Register event handlers.
         _fontFamilyTextBox.TextChanged += OnFontFamilyTextBoxTextChanged;
         _fontFamilyTextBox.LostFocus += OnFontFamilyTextBoxLostFocus;
         _fontFamilyListBox.SelectionChanged += OnFontFamilyListBoxSelectionChanged;
         _fontSizeTextBox.TextChanged += OnFontSizeTextBoxTextChanged;
         _fontSizeListBox.SelectionChanged += OnFontSizeListBoxSelectionChanged;
         _typefaceListBox.SelectionChanged += OnTypefaceListBoxSelectionChanged;
         _underlineCheckBox.Checked += OnTextDecorationCheckBoxChanged;
         _underlineCheckBox.Unchecked += OnTextDecorationCheckBoxChanged;
         _baselineCheckBox.Checked += OnTextDecorationCheckBoxChanged;
         _baselineCheckBox.Unchecked += OnTextDecorationCheckBoxChanged;
         _strikethroughCheckBox.Checked += OnTextDecorationCheckBoxChanged;
         _strikethroughCheckBox.Unchecked += OnTextDecorationCheckBoxChanged;
         _overlineCheckBox.Checked += OnTextDecorationCheckBoxChanged;
         _overlineCheckBox.Unchecked += OnTextDecorationCheckBoxChanged;
     }


     private void OnLoaded(object sender, RoutedEventArgs eventArgs)
     {
         // 调用PropertyChanged处理程序来初始化模板部件   
         OnFontFamiliesChanged();
         OnSelectedFontSizeChanged();
         OnSelectedTextDecorationsChanged();
     }


     private void OnUnloaded(object sender, RoutedEventArgs e)
     {
         _backgroundWorker?.CancelAsync();
     }


     private void OnFontFamilyTextBoxTextChanged(object sender, TextChangedEventArgs eventArgs)
     {
         // 只有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         // 在列表中查找匹配的条目
         var items = (IEnumerable<FontFamilyDescription>)_fontFamilyListBox.ItemsSource;
         var matchingItem = items.FirstOrDefault(item => string.Compare(item.DisplayName, _fontFamilyTextBox.Text, true, CultureInfo.CurrentCulture) == 0);
         if (matchingItem != null)
         {
             SelectedFontFamily = matchingItem.FontFamily;
             return;
         }

         // 找不到完全匹配。 查看文本是否是匹配的前缀
         matchingItem = items.FirstOrDefault(item => item.DisplayName.StartsWith(_fontFamilyTextBox.Text, true, null));
         if (matchingItem != null)
         {
             SelectedFontFamily = matchingItem.FontFamily;
             return;
         }

         // 找不到前缀匹配。 进行模糊搜索。
         float bestMatchValue = -1;
         FontFamilyDescription bestMatchItem = null;
         foreach (var item in _fontFamilyListBox.Items.OfType<FontFamilyDescription>())
         {
             float match = StringHelper.ComputeMatch(_fontFamilyTextBox.Text, item.DisplayName);
             if (match > bestMatchValue)
             {
                 bestMatchValue = match;
                 bestMatchItem = item;
             }
         }

         if (bestMatchItem != null)
             SelectedFontFamily = bestMatchItem.FontFamily;
     }


     private void OnFontFamilyTextBoxLostFocus(object sender, RoutedEventArgs eventArgs)
     {
         _isInternalUpdate = true;

         // 将正确的文本复制到文本框
         var selectedItem = _fontFamilyListBox.SelectedItem as FontFamilyDescription;
         if (selectedItem != null)
             _fontFamilyTextBox.Text = selectedItem.DisplayName;

         _isInternalUpdate = false;
     }


     private void OnFontFamilyListBoxSelectionChanged(object sender, SelectionChangedEventArgs eventArgs)
     {
         // 有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         var selectedItem = _fontFamilyListBox.SelectedItem as FontFamilyDescription;
         if (selectedItem != null)
             SelectedFontFamily = selectedItem.FontFamily;
     }


     private void OnFontSizeTextBoxTextChanged(object sender, TextChangedEventArgs eventArgs)
     {
         // 只有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         // 列表中查找匹配的条目
         double newSize;
         bool isValid = double.TryParse(_fontSizeTextBox.Text, out newSize);
         if (isValid)
         {
             SelectedFontSize = FontHelper.PointsToPixels(newSize);
             return;
         }
     }


     private void OnFontSizeListBoxSelectionChanged(object sender, SelectionChangedEventArgs eventArgs)
     {
         // 只有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         var selectedItem = _fontSizeListBox.SelectedItem;
         if (selectedItem != null)
             SelectedFontSize = FontHelper.PointsToPixels((double)selectedItem);
     }


     private void OnTypefaceListBoxSelectionChanged(object sender, SelectionChangedEventArgs eventArgs)
     {
         // 只有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         var selectedItem = _typefaceListBox.SelectedItem as TypefaceDescription;
         if (selectedItem != null)
         {
             var typeface = selectedItem.Typeface;
             SelectedFontStretch = typeface.Stretch;
             SelectedFontStyle = typeface.Style;
             SelectedFontWeight = typeface.Weight;
         }
     }


     private void OnTextDecorationCheckBoxChanged(object sender, RoutedEventArgs eventArgs)
     {
         // 只有在用户造成更改时才处理
         if (_isInternalUpdate)
             return;

         var textDecorations = new TextDecorationCollection();

         if (_underlineCheckBox.IsChecked.GetValueOrDefault())
             textDecorations.Add(TextDecorations.Underline);

         if (_baselineCheckBox.IsChecked.GetValueOrDefault())
             textDecorations.Add(TextDecorations.Baseline);

         if (_strikethroughCheckBox.IsChecked.GetValueOrDefault())
             textDecorations.Add(TextDecorations.Strikethrough);

         if (_overlineCheckBox.IsChecked.GetValueOrDefault())
             textDecorations.Add(TextDecorations.OverLine);

         textDecorations.Freeze();
         SelectedTextDecorations = textDecorations;
     }


     private void OnFontFamiliesChanged()
     {
         if (_fontFamilyListBox == null)
             return;

         // 填充字体列表框
         if (FontFamilies == null)
         {
             _fontFamilyListBox.ItemsSource = null;
             return;
         }

         // 为每个字体系列创建FontFamilyDescription。
         // 在后台执行,因为这可能需要一段时间
         IsLoading = true;
         _backgroundWorker = new BackgroundWorker();
         _backgroundWorker.DoWork += CreateFontFamilyDescriptions;
         _backgroundWorker.ProgressChanged += OnWorkerProgressChanged;
         _backgroundWorker.RunWorkerCompleted += OnWorkerCompleted;
         _backgroundWorker.WorkerReportsProgress = true;
         _backgroundWorker.WorkerSupportsCancellation = true;
         _backgroundWorker.RunWorkerAsync(FontFamilies);
     }


     /// 
     /// 当未处理的 Keyboard.PreviewKeyDown 附加事件在其路由中到达派生自此类的元素时,调用此方法。 
     /// 实现此方法以添加此事件的类处理
     /// 
     protected override void OnPreviewKeyDown(KeyEventArgs e)
     {
         if (e == null)
             throw new ArgumentNullException(nameof(e));

         if (e.Key == Key.Escape && _backgroundWorker.IsBusy)
         {
             // 取消加载字体系列(如果正在进行中)
             _backgroundWorker.CancelAsync();
             e.Handled = true;
         }

         base.OnPreviewKeyDown(e);
     }


     private void CreateFontFamilyDescriptions(object sender, DoWorkEventArgs eventArgs)
     {
         var fontFamilies = (ICollection<FontFamily>)eventArgs.Argument;
         double i = 0;
         int numberOfFontFamilies = fontFamilies.Count;

         var items = new List<FontFamilyDescription>(numberOfFontFamilies);
         foreach (var fontFamily in fontFamilies)
         {
             // 检查用户是否已取消加载过程.
             if (_backgroundWorker.CancellationPending)
             {
                 eventArgs.Result = items;
                 return;
             }

             // Load font family.
             var description = new FontFamilyDescription
             {
                 DisplayName = FontHelper.GetDisplayName(fontFamily.FamilyNames),
                 FontFamily = fontFamily,
                 IsSymbolFont = FontHelper.IsSymbolFont(fontFamily),
             };
             items.Add(description);

             // 报告进度
             i++;
             int progress = (int)(i / numberOfFontFamilies * 100);
             _backgroundWorker.ReportProgress(progress);
         }

         // 按显示名称对项目排序
         items.Sort((a, b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.CurrentCulture));
         eventArgs.Result = items;
     }


     private void OnWorkerProgressChanged(object sender, ProgressChangedEventArgs eventArgs)
     {
         // TODO: 我们可以使用进度条而不是动画
     }


     private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs eventArgs)
     {
         if (eventArgs.Error == null)
             _fontFamilyListBox.ItemsSource = (IEnumerable)eventArgs.Result;

         IsLoading = false;
         OnSelectedFontFamilyChanged();
         OnSelectedTypefaceChanged();
     }


     private void OnSelectedFontFamilyChanged()
     {
         if (_fontFamilyListBox == null)
             return;

         _isInternalUpdate = true;

         // 在列表框中选择匹配的条目
         IEnumerable<FontFamilyDescription> fontFamilyItems = (IEnumerable<FontFamilyDescription>)_fontFamilyListBox.ItemsSource;
         var selectedItem = fontFamilyItems.FirstOrDefault(item => item.FontFamily.Equals(SelectedFontFamily));
         _fontFamilyListBox.SelectedItem = selectedItem;

         // 获取显示名称
         var displayName = (selectedItem != null) ? selectedItem.DisplayName : string.Empty;

         // 滚动列表框条目进入视图
         if (selectedItem != null)
             _fontFamilyListBox.ScrollIntoView(selectedItem);

         // 如果文本框尚未包含匹配的文本,更新文本框。
         // 如果光标当前位于文本框中(用户正在键入),则不执行任何操作。
         if (!_fontFamilyTextBox.IsKeyboardFocused && string.Compare(_fontFamilyTextBox.Text, displayName, true, CultureInfo.CurrentCulture) != 0)
             _fontFamilyTextBox.Text = displayName;

         // ----- 初始化字体列表.
         // 填充字体列表框
         if (SelectedFontFamily == null)
         {
             _typefaceListBox.ItemsSource = null;
         }
         else
         {
             var typefaces = SelectedFontFamily.GetTypefaces();

             // 为每个字体系列创建一个文本块
             var items = new List<TypefaceDescription>(typefaces.Count);
             foreach (var typeface in typefaces)
             {
                 var item = new TypefaceDescription
                 {
                     DisplayName = FontHelper.GetDisplayName(typeface.FaceNames),
                     FontFamily = SelectedFontFamily,
                     IsSymbolFont = FontHelper.IsSymbolFont(SelectedFontFamily),
                     Typeface = typeface,
                 };

                 items.Add(item);
             }

             // 按显示名称对项目进行排序,并将其分配给列表框
             items.Sort((a, b) => FontHelper.Compare(a.Typeface, b.Typeface));
             _typefaceListBox.ItemsSource = items;

             // 更新字体控件
             OnSelectedTypefaceChanged();
         }

         _isInternalUpdate = false;
     }


     private void OnSelectedFontSizeChanged()
     {
         if (_fontSizeListBox == null)
             return;

         _isInternalUpdate = true;

         // 在列表框中选择匹配的条目
         var items = (IEnumerable<double>)_fontSizeListBox.ItemsSource ?? Enumerable.Empty<double>();

         double points = FontHelper.PixelsToPoints(SelectedFontSize);
         double selectedItem = items.FirstOrDefault(item => Numeric.AreEqual(item, points, 0.01f));

         if (selectedItem > 0)
         {
             _fontSizeListBox.SelectedItem = selectedItem;

             // 滚动列表框条目进入视图
             _fontSizeListBox.ScrollIntoView(_fontSizeListBox.SelectedItem);
         }
         else
         {
             _fontSizeListBox.SelectedItem = null;
         }

         // 如果文本框尚未包含匹配的文本,请更新文本框。
         // 如果光标当前位于文本框中(用户正在键入),则不执行任何操作
         if (!_fontSizeTextBox.IsKeyboardFocused && string.Compare(_fontSizeTextBox.Text, points.ToString(CultureInfo.CurrentCulture), true, CultureInfo.CurrentCulture) != 0)
             _fontSizeTextBox.Text = points.ToString(CultureInfo.CurrentCulture);

         _isInternalUpdate = false;
     }


     private void OnSelectedTypefaceChanged()
     {
         if (_typefaceListBox == null)
             return;

         _isInternalUpdate = true;

         var selectedTypeface = new Typeface(SelectedFontFamily, SelectedFontStyle, SelectedFontWeight, SelectedFontStretch);

         // 在列表框中选择匹配的条目
         var items = (IEnumerable<TypefaceDescription>)_typefaceListBox.ItemsSource ?? Enumerable.Empty<TypefaceDescription>();
         var selectedItem = items.FirstOrDefault(item => FontHelper.Compare(selectedTypeface, item.Typeface) == 0);
         if (selectedItem != null)
         {
             _typefaceListBox.SelectedItem = selectedItem;

             // 滚动列表框条目进入视图
             _typefaceListBox.ScrollIntoView(selectedItem);
         }

         _isInternalUpdate = false;
     }


     private void OnSelectedTextDecorationsChanged()
     {
         if (_underlineCheckBox == null)
             return;

         _isInternalUpdate = true;

         bool underline = false;
         bool baseline = false;
         bool strikethrough = false;
         bool overline = false;

         // 找出使用的文本装饰
         TextDecorationCollection textDecorations = SelectedTextDecorations;
         if (textDecorations != null)
         {
             foreach (TextDecoration textDecoration in textDecorations)
             {
                 switch (textDecoration.Location)
                 {
                     case TextDecorationLocation.Underline:
                         underline = true;
                         break;
                     case TextDecorationLocation.Baseline:
                         baseline = true;
                         break;
                     case TextDecorationLocation.Strikethrough:
                         strikethrough = true;
                         break;
                     case TextDecorationLocation.OverLine:
                         overline = true;
                         break;
                 }
             }
         }

         _underlineCheckBox.IsChecked = underline;
         _baselineCheckBox.IsChecked = baseline;
         _strikethroughCheckBox.IsChecked = strikethrough;
         _overlineCheckBox.IsChecked = overline;
         _isInternalUpdate = false;
     }
     #endregion
 }

FontFamilyDescription

public class FontFamilyDescription
 {
      /// 
      /// 获取或设置字体系列的显示名称
      /// 
      public string DisplayName { get; set; }


      /// 
      /// 获取或设置字体系列
      /// 
      public FontFamily FontFamily { get; set; }


      /// 
      /// 获取或设置一个值,该值指示字体是否为符号字体
      /// 
      public bool IsSymbolFont { get; set; }
  }

TypefaceDescription

public class TypefaceDescription
{
     /// 
     /// 获取或设置字体的显示名称
     /// 
     public string DisplayName { get; set; }


     /// 
     /// 获取或设置字体
     /// 
     public FontFamily FontFamily { get; set; }


     /// 
     /// 获取或设置一个值,该值指示字体是否为符号字体。
     /// 
     public bool IsSymbolFont { get; set; }


     /// 
     /// 获取或设置字体
     /// 
     public Typeface Typeface { get; set; }
 }

你可能感兴趣的:(游戏引擎/编辑器,开发)