2009-03-10 18 views
17

Przy użyciu WPF, jaki jest najskuteczniejszy sposób pomiaru dużej liczby krótkich łańcuchów? W szczególności chciałbym określić wysokość wyświetlania każdego ciągu, biorąc pod uwagę jednolite formatowanie (tę samą czcionkę, rozmiar, wagę itp.) I maksymalną szerokość, jaką może zająć ciąg znaków?Pomiar tekstu w WPF

+1

samo pytanie na forum MSDN dostał jakieś lepsze rozwiązania: http://social.msdn.microsoft.com/Forums/en-US/wpf/ thread/a450b0aa-7086-4145-9eff-a779571b6187/ – srgstm

Odpowiedz

12

Najbardziej niskopoziomową techniką (a więc dającą najwięcej możliwości twórczej optymalizacji) jest użycie GlyphRuns.

To nie jest bardzo dobrze udokumentowane, ale napisałem do góry trochę przykład tutaj:

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

Przykład odrabia długość napisu jako niezbędny krok przed czynią je.

3

Można użyć właściwości DesiredSize na wytopione TextBox, aby uzyskać wysokość i szerokość

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

Jeśli masz dużą liczbę strun może być szybciej do pierwszego wstępnego calualte wysokość i szerokość każdego pojedyncza litera i symbol w danej czcionce, a następnie wykonaj obliczenia na podstawie znaków smyczkowych. To może nie być 100% acurate ze względu na kerning itp.

5

Jest to bardzo proste i wykonane przez klasę FormattedText! Wypróbuj.

+0

FormattedText nie jest dostępny w UniversalWindows, pomóżcie mi! –

5

W WPF:

Pamiętaj, aby zadzwonić Measure() na TextBlock przed przeczytaniem właściwość DesiredSize.

Jeśli TextBlock powstał on-the-fly, i jeszcze nie widać, trzeba zadzwonić do środka() po pierwsze, tak jak poniżej:

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

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

w Silverlight:

Nie trzeba mierzyć.

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

Kompletny kod wygląda następująco:

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 
}