2011-08-10 1 views
5

J'énumère la liste des fontfamilies et les lie à la zone de liste déroulante, le problème est lorsqu'une police du système est corrompue. L'ensemble de l'application va se bloquer. De toute façon je suis capable de lier à systemfontfamilies encore capable d'ignorer la police qui a l'erreur d'affichage? Le code suivant fonctionne correctement si la liaison de fontfamily dans le itemtemplate est commentée.Erreur SystemFontFamilies lors de la liaison à la zone de liste déroulante

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

le message d'erreur qui s'est comme suit

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() 

S'il vous plaît aider. THanks

Répondre

4

J'ai eu le même problème. Dans un éditeur richtextbox, je remplis une boîte de dialogue du ruban avec toutes les familles de polices disponibles et j'attache cette police à cet élément spécifique dans la liste déroulante afin qu'un utilisateur voie immédiatement à quoi ressemble la police.

Lorsqu'il y avait une police sur le système qui ne pouvait pas être rendue par WPF, l'application se bloquait.

En regardant la pile dans l'observateur d'événements, j'ai remarqué que WPF essaye d'instancier un objet du type System.Windows.Media.GlyphTypeface. J'ai découvert que, lorsque j'essaie d'instancier moi-même cet objet dans le code (via le type System.Windows.Media.Typeface) et que la fonction TryGetGlyphTypeface() renvoie false pour mes paramètres de police spécifiques, cette police n'est pas utilisable dans WPF .

Le code qui a résolu le problème pour moi:

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); 
     } 
    } 

Pour éviter que ce code doit être exécuté à chaque fois que je charge le combobox (et c'est pas mal parce qu'il est dans un contrôle utilisateur), je fais une fois au début de l'application et enregistrer le tableau de polices utilisables dans une variable globale.

+0

Notez, cependant, qu'il est _normal_ pour 'TryGetGlyphTypeface()' de retourner 'null' pour les familles de polices valides, c'est-à-dire les polices composites. Ce n'est pas parce que le fichier retourne "null" que le fichier de police est corrompu (bien sûr, si vous utilisez le 'GlyphTypeface' lui-même, vous devrez faire plus de travail pour le récupérer, en décomposant le composite police ... mais cela ne fait pas partie du problème ici). –

0

Ok, 5 ans plus tard, voici une autre solution:

Declare ce code au 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> 

Et utiliser cette 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; 
} 

et appliquer les ressources à la 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

Voir note dans l'autre réponse. Cette approche ignorera les polices composites valides, en plus des polices contenant des fichiers de polices endommagés. –

+0

Et que pouvons-nous faire pour éviter de manquer certaines polices? Wrapping à l'intérieur du 'try catch' avec le' returnList.Add (font); 'à la fin? –

+0

Comme je l'ai écrit dans mon autre commentaire, quand vous rencontrez une police composite, vous devez faire plus de travail pour obtenir une vraie police. C'est à dire. examinez ses 'FamilyMaps' pour trouver un' FontFamily' approprié qui supporte les points de code Unicode que vous essayez de rendre. Et oui, comme pour les polices invalides/corrompues, la gestion des exceptions peut résoudre ce problème.Bien que, à mon humble avis, si vous allez faire cela, vous devez au moins informer l'utilisateur _which_ police a provoqué l'exception, afin qu'ils puissent réparer leur système. –

Questions connexes