绑定到组合框时出现SystemFontFamilies错误

时间:2011-08-10 05:49:58

标签: wpf fonts

我列举了fontfamilies列表并绑定到combobox,问题是当系统中的字体有损坏时。整个应用程序将崩溃。我能以任何方式绑定到systemfontfamilies但能够跳过显示错误的字体吗?

如果注释了itemtemplate中的fontfamily绑定,则以下代码运行正常。

 <ComboBox x:Name="comboFonts"
                          Grid.IsSharedSizeScope="True"
                          Grid.Row="0" Grid.Column="1"
                          ItemsSource="{Binding Source={x:Static Member=Fonts.SystemFontFamilies}}"
                          SelectedItem="{Binding FontFamily, Mode=TwoWay}"
                          HorizontalAlignment="Stretch">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="FontName"></ColumnDefinition>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Source}" HorizontalAlignment="Left"/>
                    <Label FontFamily="{Binding FallbackValue=Verdana}" HorizontalAlignment="Right">Sample</Label>
                </Grid>

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

获取的错误消息如下

Message=Input file or data stream does not conform to the expected file format specification.
Source=PresentationCore
StackTrace:
   at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr)
   at MS.Internal.Text.TextInterface.Font.CreateFontFace()
   at MS.Internal.Text.TextInterface.Font.AddFontFaceToCache()
   at MS.Internal.Text.TextInterface.Font.GetFontFace()

请帮忙。感谢

2 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。 在richtextbox编辑器中,我使用所有可用的字体系列填充功能区combox,并将该字体附加到组合框中的特定项目,以便用户立即看到字体的外观。

当系统中存在无法由WPF呈现的字体时,应用程序将崩溃。

查看事件查看器中的stacktrace,我注意到WPF尝试实例化System.Windows.Media.GlyphTypeface类型的对象。 我发现,当我尝试在代码中自己实例化该对象(通过System.Windows.Media.Typeface类型)并且TryGetGlyphTypeface()函数将为我的特定字体设置返回false时,该字体在WPF中不可用。

为我解决问题的代码:

    foreach (FontFamily aFontFamily in Fonts.SystemFontFamilies)
    {
        // Instantiate a TypeFace object with the font settings you want to use
        Typeface ltypFace = new Typeface(aFontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
        // Try to create a GlyphTypeface object from the TypeFace object
        GlyphTypeface lglyphTypeFace;
        if (ltypFace.TryGetGlyphTypeface(out lglyphTypeFace))
        {
            // Creation of the GlyphTypeface worked. You can use the font
            RibbonGalleryItem lribItem = new RibbonGalleryItem();
            lribItem.Content = aFontFamily.Source;
            lribItem.FontFamily = aFontFamily;
            lribGalCatFont.Items.Add(lribItem);
        }
    }

为了防止每次加载组合框时都必须执行此代码(由于它位于用户控件中,这个代码很多),我在应用程序启动时执行此操作一次并将可用字体数组保存在全局变量。

答案 1 :(得分:0)

好的,5年后,这是另一个解决方案:

Window.Resource

声明此代码
<CollectionViewSource x:Key="MyFonts" Source="{Binding Source={x:Static Fonts.SystemFontFamilies}, Converter={StaticResource FontToSupportedGliphConverter}}">
    <CollectionViewSource.SortDescriptions>
        <componentModel:SortDescription PropertyName="Source" />
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

<Style x:Key="FontStyle">
    <Setter Property="Control.FontFamily" Value="{Binding .}" />
    <Setter Property="Control.FontSize" Value="16" />
</Style>

<DataTemplate x:Key="FontTemplate">
    <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ScrollViewer.IsDeferredScrollingEnabled="True">
        <TextBlock Style="{StaticResource FontStyle}" Text="{Binding .}" ToolTip="{Binding .}" />
    </VirtualizingStackPanel>
</DataTemplate>

并使用此Converter

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    var list = value as IReadOnlyCollection<FontFamily>;

    if (list == null)
        return DependencyProperty.UnsetValue;

    var returnList = new List<FontFamily>();
    foreach (FontFamily font in list)
    {
        //Instantiate a TypeFace object with the font settings you want to use
        Typeface ltypFace = new Typeface(font, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);

        //Try to create a GlyphTypeface object from the TypeFace object
        GlyphTypeface lglyphTypeFace;
        if (ltypFace.TryGetGlyphTypeface(out lglyphTypeFace))
        {
            returnList.Add(font);
        }
    }

    return returnList;
}

将资源应用于ComboBox

<ComboBox x:Name="FreeTextFontComboBox" Margin="10,5" 
          MinWidth="100" MaxWidth="110" IsEditable="True"
          ItemTemplate="{DynamicResource FontTemplate}" 
          SelectedItem="{Binding Source={x:Static prop:Settings.Default}, 
          Path=FreeTextFontFamily}">
    <ComboBox.ItemsSource>
        <Binding Source="{StaticResource MyFonts}" />
    </ComboBox.ItemsSource>
</ComboBox>