首页 > 解决方案 > 在 WPF 中结合文本换行和收缩

问题描述

在我的 WPF 应用程序中,我有一个相对较小的有限宽度框,我需要在其中显示一些用户输入的文本。文本实际上可以预期在 1 到 5 个单词之间,但单词很容易比框大。

如果文本太长,但包含多个可以分成几行的单词,我希望文本换行。但是,如果任何单个单词太大而无法容纳,那么我希望文本大小缩小,直到该单词足够小以容纳,无论该文本是否也在换行。我不在乎文本占用了多少垂直空间。

这是我在 Excel 中手动组合的一个示例,以演示预期的行为: 例子

在示例 1 中,整个文本都适合该框。
在示例 2 中,文本是两个单词,因此可以在不缩小文本的情况下进行换行。
在示例 3 中,单个单词太长,因此必须缩小文本。
在示例 4 中,文本可以被换行,但它仍然包含一个太长而无法容纳的单词,因此必须缩小文本,直到最长的单词可以容纳。

如何在 WPF 中实现这一点?我一直无法找到一个组合ViewBoxTextBlock.TextWrapping哪个做到这一点。

编辑:
如果我必须手动执行此操作(这将是一场噩梦),那么至少有一种方法可以弄清楚 TextBlock 决定什么是“线”?我需要知道它将如何分解文本,然后才能确定是否有任何“行”会太长。

标签: wpftextviewword-wraptext-size

解决方案


您必须手动执行此操作。以下代码示例调整 a 的字体大小,TextBox直到所有文本都适合视口(文本渲染的最大可用空间)。您必须从注册到TextBoxBase.TextChanged事件的事件处理程序中执行此方法:

protected void ResizeTextToFit(TextBox textBox)
{
  // Make sure the first line is always visible
  textBox.ScrollToVerticalOffset(0);

  bool fontSizeHasChanged = false;

  // Shrink to fit as long
  // the last visible line is not the last line or
  // the true text height is bigger than the visible text height
  // and prevent font size to be set to '0'
  while (textBox.FontSize > 1 
         && (textBox.GetLastVisibleLineIndex() < textBox.LineCount - 1 
             || textBox.ExtentHeight > textBox.ViewportHeight))
  {
    fontSizeHasChanged = true;
    textBox.FontSize -= 1.0;
  }

  if (fontSizeHasChanged)
  {
    return;
  }

  // Enlarge to fit as long the last line is visible 
  // and the text height fits into the viewport
  while (textBox.GetLastVisibleLineIndex() == textBox.LineCount - 1 
         && textBox.ExtentHeight < textBox.ViewportHeight)
  {
    textBox.FontSize += 1.0;
  }
  textBox.FontSize -= 1.0;
}

你可能更喜欢扩展你自己的类TextBox来封装这个行为。

此示例依赖于TextBox具有固定Widthand的 a Height,因此它无法根据内容调整大小。


推荐阅读