WPF技术问询:如何获取开启TextTrimming的TextBlock的隐藏文本范围
WPF TextBlock开启文本裁剪后获取被裁剪内容或裁剪索引的方法
WPF的TextBlock控件在设置TextTrimming为WordEllipsis或CharacterEllipsis时,没有内置属性直接返回被裁剪的文本或裁剪位置,需要通过计算文本的显示宽度来实现。
核心思路
利用FormattedText类模拟TextBlock的文本渲染,计算每个字符(或单词)的显示宽度,结合控件的可用宽度(扣除内边距)和省略号的宽度,逐步判断文本在哪一处开始超过显示范围,从而确定裁剪索引。
实现代码
下面是一个工具方法,可直接用于获取裁剪索引,进而得到被裁剪的文本:
using System.Globalization; using System.Windows; using System.Windows.Media; public static class TextBlockHelper { public static int GetTextTrimmingIndex(TextBlock textBlock) { if (textBlock == null || string.IsNullOrEmpty(textBlock.Text)) return -1; // 创建与TextBlock格式一致的FormattedText对象 var baseFormattedText = new FormattedText( textBlock.Text, CultureInfo.CurrentCulture, textBlock.FlowDirection, new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch), textBlock.FontSize, textBlock.Foreground); // 计算省略号的显示宽度 var ellipsisWidth = new FormattedText( "...", CultureInfo.CurrentCulture, textBlock.FlowDirection, new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch), textBlock.FontSize, textBlock.Foreground).Width; // 计算控件的可用显示宽度 double availableWidth = textBlock.ActualWidth - textBlock.Padding.Left - textBlock.Padding.Right; double currentTotalWidth = 0; int trimIndex = textBlock.Text.Length; if (textBlock.TextTrimming == TextTrimming.WordEllipsis) { // 按单词分割处理,匹配WordEllipsis的裁剪逻辑 string[] words = textBlock.Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int currentWordPos = 0; foreach (var word in words) { // 获取当前单词的起始索引 int wordStartIndex = textBlock.Text.IndexOf(word, currentWordPos); // 计算当前单词的宽度 double wordWidth = baseFormattedText.BuildHighlightGeometry(new Point(currentTotalWidth, 0), wordStartIndex, word.Length).Bounds.Width; // 判断加上当前单词和省略号后是否超出可用宽度 if (currentTotalWidth + wordWidth + ellipsisWidth > availableWidth) { trimIndex = wordStartIndex; break; } // 累加单词宽度和后续空格的宽度 currentTotalWidth += wordWidth; if (wordStartIndex + word.Length < textBlock.Text.Length) { double spaceWidth = baseFormattedText.BuildHighlightGeometry(new Point(currentTotalWidth, 0), wordStartIndex + word.Length, 1).Bounds.Width; currentTotalWidth += spaceWidth; } currentWordPos = wordStartIndex + word.Length + 1; } } else if (textBlock.TextTrimming == TextTrimming.CharacterEllipsis) { // 按单个字符处理,匹配CharacterEllipsis的裁剪逻辑 for (int i = 0; i < textBlock.Text.Length; i++) { double charWidth = baseFormattedText.BuildHighlightGeometry(new Point(currentTotalWidth, 0), i, 1).Bounds.Width; if (currentTotalWidth + charWidth + ellipsisWidth > availableWidth) { trimIndex = i; break; } currentTotalWidth += charWidth; } } return trimIndex; } }
使用示例
在TextBlock加载完成后调用该方法,即可获取裁剪索引和被裁剪文本:
// 假设xaml中定义的TextBlock名为text1 private void TextBlock_Loaded(object sender, RoutedEventArgs e) { int trimIndex = TextBlockHelper.GetTextTrimmingIndex(text1); if (trimIndex != -1 && trimIndex < text1.Text.Length) { string trimmedContent = text1.Text.Substring(trimIndex); // 示例中trimmedContent将是"LONG TEXT",trimIndex为10 } }
注意事项
- 必须在TextBlock加载完成后调用(比如
Loaded事件中),否则ActualWidth可能未正确计算。 - 该方法会模拟TextBlock的文本渲染逻辑,计算结果与实际显示的裁剪位置一致。
内容的提问来源于stack exchange,提问作者ErinQvnm
相关产品推荐
相关产品推荐

