Как получить обрезанный текст TextBlock, когда TextTrimming установлен на «WordEllipsis» или «CharacterEllipsis»?
Например, этот код:
<TextBlock Name = "text1" FontSize = "12" Width = "94" Text = "THIS IS A LONG TEXT" TextTrimming = "WordEllipsis"/>
отображает: THIS IS A...
Как получить обрезанный текст: LONG TEXT или индекс обрезания строки: 10
Я знаю, что значение Text не меняется. Может быть, есть обходной путь, чтобы получить обрезанный текст?
Тогда я неправильно вас понял. Вы должны измерить текст.





Вам нужно вручную измерить текст (со всеми примененными стилями шрифта).
Общее решение, которое также работает с TextTrimming, установленным на TextTrimming.WordEllipsis, должно итеративно находить позицию последнего символа.
Поскольку нет связанного API, мы должны сделать это сложным путем и итеративно тестировать, пока мы больше не получим исключение. Другого пути нет (требование знать точную текстовую часть, которая обрезает доступную текстовую область, обычно не имеет смысла).
Однако, когда для TextTrimming установлено значение TextTrimming.CharacterEllipsis, исключений не будет. Это связано с тем, что обрезка на основе символов дает предсказуемый результат, в отличие от обрезки слов, когда длина слов является случайной (поскольку слова неизвестны). Это означает, что случай на основе TextTrimming.CharacterEllipsis более удобен для производительности.
Окончательное решение, поддерживающее TextTrimming.WordEllipsis и TextTrimming.CharacterEllipsis, может выглядеть следующим образом:
public string GetHiddenRangeOfTrimmedText(TextBlock textBlock)
{
var typeFace = new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch);
var numberSubstitution = new NumberSubstitution(NumberSubstitution.GetCultureSource(textBlock), CultureInfo.CurrentUICulture, NumberSubstitution.GetSubstitution(textBlock));
// Define ellipsis using four ellipsis characters (instead of three).
// This is because ellipsis is rendered using three visible and one hidden ellipsis characters.
var formattedEllipsisText = new FormattedText(
"....",
CultureInfo.CurrentUICulture,
textBlock.FlowDirection,
typeFace,
textBlock.FontSize,
textBlock.Foreground,
numberSubstitution,
VisualTreeHelper.GetDpi(textBlock).PixelsPerDip);
double clippingOffset = textBlock.ActualWidth - formattedEllipsisText.Width - textBlock.Padding.Right;
var clippingPosition = new Point(clippingOffset, 0);
TextPointer clippingPositionTextPointer = null;
do
{
try
{
clippingPositionTextPointer = textBlock.GetPositionFromPoint(clippingPosition, true);
}
catch (ArgumentException)
{
if (clippingPosition.X == 0)
{
return string.Empty;
}
clippingPosition.Offset(-1, 0);
}
if (clippingPositionTextPointer is not null)
{
break;
}
} while (clippingPosition.X >= 0);
var clippedTextRange = new TextRange(clippingPositionTextPointer, textBlock.ContentEnd);
string clippedText = clippedTextRange.Text;
return clippedText;
}
Значение свойства Text не меняется. Только текстовое представление TextBlock изменяется в том смысле, что оно заменяет отсеченный визуализированный текст многоточием.