Как рассчитать ширину текстового блока WPF для его известного размера шрифта и символов?
допустим, у меня есть TextBlock
текст "Текст" и размер шрифта 10.0.
Как я могу вычислить соответствующие TextBlock
ширина?
6 ответов:
использовать
FormattedText
класса.Я сделал вспомогательную функцию в моем коде:
private Size MeasureString(string candidate) { var formattedText = new FormattedText( candidate, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.textBlock.FontFamily, this.textBlock.FontStyle, this.textBlock.FontWeight, this.textBlock.FontStretch), this.textBlock.FontSize, Brushes.Black, new NumberSubstitution(), 1); return new Size(formattedText.Width, formattedText.Height); }
он возвращает независимые от устройства пиксели, которые могут быть использованы в макете WPF.
для записи... Я предполагаю, что op'ER пытается программно определить ширину, которую будет занимать текстовый блок после добавления в визуальное дерево. IMO лучшее решение, чем formattedText (как вы обрабатываете что-то вроде textWrapping?) было бы использовать меру и организовать на образце TextBlock. например,
var textBlock = new TextBlock { Text = "abc abd adfdfd", TextWrapping = TextWrapping.Wrap }; // auto sized textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); textBlock.Arrange(new Rect(textBlock.DesiredSize)); Debug.WriteLine(textBlock.ActualWidth); // prints 80.323333333333 Debug.WriteLine(textBlock.ActualHeight);// prints 15.96 // constrain the width to 16 textBlock.Measure(new Size(16, Double.PositiveInfinity)); textBlock.Arrange(new Rect(textBlock.DesiredSize)); Debug.WriteLine(textBlock.ActualWidth); // prints 14.58 Debug.WriteLine(textBlock.ActualHeight);// prints 111.72
Я решил эту проблему, добавив путь привязки к элементу в бэкэнд-коде:
<TextBlock x:Name="MyText" Width="{Binding Path=ActualWidth, ElementName=MyText}" />
я обнаружил, что это гораздо более чистое решение, чем добавление всех накладных расходов вышеуказанных ссылок, таких как FormattedText, в мой код.
после того, как я смог это сделать:
double d_width = MyText.Width;
предоставленное решение было подходящим для .Net Framework 4.5, однако с масштабированием Windows 10 DPI и Framework 4.6.X добавляя различные степени поддержки для него, конструктор, используемый для измерения текста, теперь помечен
[Obsolete]
, вместе с любыми конструкторами на этом методе, которые не включают
Я нашел некоторые методы, которые работают нормально...
/// <summary> /// Get the required height and width of the specified text. Uses Glyph's /// </summary> public static Size MeasureText(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize) { Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch); GlyphTypeface glyphTypeface; if (!typeface.TryGetGlyphTypeface(out glyphTypeface)) { return MeasureTextSize(text, fontFamily, fontStyle, fontWeight, fontStretch, fontSize); } double totalWidth = 0; double height = 0; for (int n = 0; n < text.Length; n++) { ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]]; double width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize; double glyphHeight = glyphTypeface.AdvanceHeights[glyphIndex] * fontSize; if (glyphHeight > height) { height = glyphHeight; } totalWidth += width; } return new Size(totalWidth, height); } /// <summary> /// Get the required height and width of the specified text. Uses FortammedText /// </summary> public static Size MeasureTextSize(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize) { FormattedText ft = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), fontSize, Brushes.Black); return new Size(ft.Width, ft.Height); }