2009-03-10 4 views
17

À l'aide de WPF, quel est le moyen le plus efficace de mesurer un grand nombre de chaînes courtes? Spécifiquement, je voudrais déterminer la taille d'affichage de chaque chaîne, donné le formatage uniforme (même police, taille, poids, etc.) et la largeur maximum que la chaîne peut occuper?Mesure de texte dans WPF

+1

Même question sur les forums MSDN a de meilleures solutions: http://social.msdn.microsoft.com/Forums/en-US/wpf/ thread/a450b0aa-7086-4145-9eff-a779571b6187/ – srgstm

Répondre

12

La technique la plus bas niveau (et donc donnant le plus de possibilités pour les optimisations créatives) est d'utiliser GlyphRuns.

Il est pas très bien documenté, mais j'ai écrit un petit exemple ici:

http://smellegantcode.wordpress.com/2008/07/03/glyphrun-and-so-forth/

L'exemple fonctionne sur la longueur de la chaîne comme une étape nécessaire avant de le restituer.

3

Vous pouvez utiliser la propriété DesiredSize sur une zone de texte rendu pour obtenir la hauteur et la largeur

using System.Windows.Threading; 

... 

Double TextWidth = 0; 
Double TextHeight = 0; 
... 

MyTextBox.Text = "Words to measure size of"; 
this.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new DispatcherOperationCallback(delegate(Object state) { 
     var size = MyTextBox.DesiredSize; 
     this.TextWidth = size.Width; 
     this.TextHeight = size.Height; 
     return null; 
    } 
) , null); 

Si vous avez un grand nombre de chaînes, il peut être plus rapide d'abord pré-calualte la hauteur et la largeur de chaque lettre et symbole indiviudal dans une police donnée, puis effectuez un calcul basé sur les caractères de chaîne. Cela peut ne pas être 100% exact à cause du crénage etc

5

C'est très simple et fait par la classe FormattedText! Essayez-le.

+0

FormattedText n'est pas disponible dans UniversalWindows, aidez-moi! –

5

En WPF:

Rappelez-vous d'appeler mesure() sur le TextBlock avant de lire la propriété DesiredSize.

Si le TextBlock a été créé sur la volée, et non encore montré, vous devez appeler Mesure() Tout d'abord, comme ceci:

MyTextBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 

return new Size(MyTextBlock.DesiredSize.Width, MyTextBlock.DesiredSize.Height); 

Dans Silverlight:

Pas besoin de mesurer.

return new Size(TextBlock.ActualWidth, TextBlock.ActualHeight); 

Le code complet ressemble à ceci:

public Size MeasureString(string s) { 

    if (string.IsNullOrEmpty(s)) { 
     return new Size(0, 0); 
    } 

    var TextBlock = new TextBlock() { 
     Text = s 
    }; 

#if SILVERLIGHT 
    return new Size(TextBlock.ActualWidth, TextBlock.ActualHeight); 
#else 
    TextBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); 

    return new Size(TextBlock.DesiredSize.Width, TextBlock.DesiredSize.Height); 
#endif 
} 
Questions connexes