Сочетание переноса текста и сжатия в WPF - PullRequest
0 голосов
/ 11 июля 2019

В моем приложении WPF у меня есть относительно небольшая коробка ограниченной ширины, в которой мне нужно отобразить некоторый текст, введенный пользователем.Реально можно ожидать, что текст будет содержать от одного до пяти слов, но слова могут легко быть больше, чем рамка.

Если текст слишком длинный, но содержит несколько слов, которые можно разбить на строки,Я бы хотел, чтобы текст был перенесен.Однако, если какое-либо отдельное слово слишком велико, чтобы его вместить, я хочу, чтобы размер текста уменьшался до тех пор, пока это слово не станет достаточно маленьким, чтобы соответствовать ему, независимо от того, переносится ли этот текст или нет.Мне все равно, сколько вертикального пространства занимает текст.

Вот пример, который я собрал вручную в Excel, чтобы продемонстрировать намеченное поведение: Example

В примере 1 весь текст помещается в поле.
В примере 2 текст состоит из двух слов, поэтому его можно переносить без сжатия текста.
В примере 3 одно слово слишком длинное, поэтому текст имеетбыть сокращенным.
В примере 4 текст может быть обернут, но он все еще содержит слово, которое слишком длинно, чтобы соответствовать, поэтому текст должен быть сжат, пока не подходит это самое длинное слово.

Как можноЯ делаю это в WPF?Мне не удалось найти комбинацию ViewBox и TextBlock.TextWrapping, которая делает это.

РЕДАКТИРОВАТЬ:
Если я сделать должнысделать это вручную (что было бы немного кошмаром), тогда есть ли хотя бы способ, чтобы я мог выяснить, что TextBlock решает, что это «линия»?Мне нужно знать, как он разбивает текст, прежде чем я смогу определить, будет ли какая-то одна «строка» слишком длинной.

1 Ответ

0 голосов
/ 11 июля 2019

Вы должны сделать это вручную.В следующем примере кода корректируется размер шрифта 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 с фиксированными Width и Height, поэтому он не может изменить размер содержимого.

...