WPF如何获取修剪文本的隐藏文本范围(启用TextTrimming)

okxuctiv  于 2023-08-07  发布在  其他
关注(0)|答案(1)|浏览(109)

当TextTrimming设置为“WordEllipsis”或“CharacterEllipsis”时,如何获取TextBlock的修剪文本?
例如,这段代码:

<TextBlock Name="text1" FontSize="12" Width="94" Text="THIS IS A LONG TEXT" TextTrimming="WordEllipsis"/>

字符串
显示器:THIS IS A...
如何获得修剪的文本:LONG TEXT或修剪字符串的索引:10

insrf1ej

insrf1ej1#

您需要手动测量文本(应用所有字体样式)。
如果TextTrimming设置为TextTrimming.WordEllipsis,一般的解决方案必须迭代地找到最后一个字符的位置。
因为没有相关的API,我们必须用艰难的方式来做,反复测试,直到我们不再得到异常为止。没有其他方法(要求知道剪辑可用文本区域的确切文本部分通常是不明智的)。
但是,当TextTrimming设置为TextTrimming.CharacterEllipsis时,不会抛出任何异常。这是因为基于字符的修剪产生了一个可预测的结果,而不是词的长度是随机的(因为词是未知的)字修剪。这意味着基于TextTrimming.CharacterEllipsis的情况更友好。
此外,查找多行TextBlock的多个隐藏文本范围是一个更复杂的场景,所提出的解决方案没有解决。
支持TextTrimming.WordEllipsisTextTrimming.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;
}

public int GetIndexOfHiddenRangeOfTrimmedText(TextBlock textBlock)
{
  string hiddenTextRange = GetHiddenRangeOfTrimmedText(textBlock);
  int indexOfHiddenTextRange = textBlock.Text.IndexOf(hiddenTextRange, StringComparison.OrdinalIgnoreCase);
  return indexOfHidenTextRange;
}

字符串

相关问题