2011-08-10 8 views
5

fontfamiliesのリストを列挙してコンボボックスにバインドすると、システムに壊れているフォントがあるときに問題が発生します。アプリケーション全体がクラッシュします。どのように私はsystemfontfamiliesにバインドすることができますまだエラーを表示しているフォントをスキップすることができますか?コンボボックスへのバインド時に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() 

を以下の通りです。 THanks

答えて

4

私は同じ問題を抱えていました。 リッチテキストボックスエディタでは、使用可能なすべてのフォントファミリでリボンコボボックスを塗りつぶして、そのフォントをコンボボックス内のその特定の項目に添付して、ユーザーがフォントの外観をすぐに見るようにします。

システム上に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

しかし、TryGetGlyphTypeface()が有効なフォントファミリ、つまりコンポジットフォントに対して 'null'を返すのは普通ではないことに注意してください。 'null'を返すだけであるから、必ずしもフォントファイルが壊れているとは限りません(もちろん、' GlyphTypeface'自体に頼っているなら、それを得るためには複合体フォント...しかし、それはここの問題の一部ではありません)。 –

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> 
+0

他の回答の注記を参照してください。この方法では、有効な合成フォントと、壊れたフォントファイルを含むフォントはスキップされます。 –

+0

フォントを紛失しないようにするにはどうすればよいですか?終わりに 'returnList.Add(font);'で 'try catch'の中に折り返しますか? –

+0

私が他のコメントで書いたように、複合フォントに遭遇したときは、本当のフォントを得るためにもっと多くの作業をする必要があります。私。 'FamilyMaps'を調べて、レンダリングしようとしているUnicodeコードポイントをサポートする適切な' FontFamily'を見つけてください。そして、無効/壊れたフォントに関しては、例外を処理することで対応できます。しかし、あなたがそれをやろうとするならば、あなたは少なくとも、そのフォントの例外を引き起こしたフォントをユーザに知らせるべきです。そうすれば、彼らは自分のシステムを修正することができます。 –

関連する問題