2009-03-10 20 views
17

Utilizzando WPF, qual è il modo più efficiente per misurare un numero elevato di stringhe corte? In particolare, mi piacerebbe determinare l'altezza di visualizzazione di ogni stringa, data una formattazione uniforme (stesso font, dimensioni, peso, ecc.) E la larghezza massima che la stringa può occupare?Misurazione del testo in WPF

+1

Stessa domanda sul forum di MSDN ottenuto alcune soluzioni migliori: http://social.msdn.microsoft.com/Forums/en-US/wpf/ thread/a450b0aa-7086-4145-9eff-a779571b6187/ – srgstm

risposta

12

La tecnica di livello più basso (e quindi la più ampia per le ottimizzazioni creative) è l'utilizzo di GlyphRuns.

Non è molto ben documentato, ma ho scritto un piccolo esempio qui:

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

L'esempio funziona la lunghezza della stringa come un passo necessario prima del rendering di esso.

3

È possibile utilizzare la proprietà DesiredSize su un TextBox reso per ottenere l'altezza e la larghezza

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

Se si dispone di un gran numero di stringhe può essere più veloce per primo pre-calualte l'altezza e la larghezza di ogni lettera e simbolo indiviudali in un determinato carattere, quindi eseguire un calcolo basato sui caratteri stringa. Questo potrebbe non essere accurato al 100% a causa di kerning ecc.

5

È molto semplice e fatto dalla classe FormattedText! Provalo.

+0

FormattedText non è disponibile in UniversalWindows, aiutatemi! –

5

In WPF:

ricordarsi di chiamare Measure() sul TextBlock prima di leggere la proprietà DesiredSize.

Se TextBlock è stato creato on-the-fly, e non ancora mostrato, è necessario chiamare Measure() prima, in questo modo:

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

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

In Silverlight:

Non c'è bisogno di misurare.

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

Il codice completo è simile al seguente:

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 
} 
Problemi correlati