Подтвердить что ты не робот

WPF RichTextBox без установленной ширины

У меня есть следующий код XAML:

<Window x:Class="RichText_Wrapping.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1">
<Grid>
    <RichTextBox Height="100" Margin="2" Name="richTextBox1">
        <FlowDocument>
            <Paragraph>
                This is a RichTextBox - if you don't specify a width, the text appears in a single column
            </Paragraph>
        </FlowDocument>
    </RichTextBox>
</Grid>

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

4b9b3361

Ответ 1

Попробуйте привязать ширину FlowDocument (в одну сторону) к ширине контейнера RichTextBox.

Работал для меня...

Ответ 2

Это подтвержденная ошибка с WPF RichTextBox. Чтобы исправить это, привяжите PageWidth документа FlowDocument к ширине RichTextBox, т.е.

<RichTextBox Name="rtb">
    <FlowDocument Name="rtbFlowDoc" PageWidth="{Binding ElementName=rtb, Path=ActualWidth}" />
</RichTextBox>

EDIT: Дайте FlowDocument имя, чтобы вы могли получить доступ к нему в коде позади и никогда не вводить новый документ потока в codebehind.

Ответ 3

Подход в в этой статье работал у меня:

WPF RichTextBox не предоставляет функции для настройки ширины к тексту. Насколько я знаю, RichTextBox использует FlowDocumentView в его визуальное дерево для рендеринга Flowdocument. Это займет чтобы отобразить его содержимое, поэтому он не будет изменять свой размер до содержание. Поскольку это внутренний класс, кажется, мы не можем переопределить процесс компоновки, чтобы RichTextBox мог настроить свой размер на текст.

Поэтому я думаю, что ваш подход находится в правильном направлении. К сожалению, на основе моих исследований нет простого способа для измерения размера отображаемого текста в RichTextBox.

Существует обходное решение, которое мы можем попробовать. Мы можем пропустить поток документа в RichTextBox рекурсивно, чтобы получить все объекты Run и Paragraph. Затем мы преобразуем их в формат FormattedText, чтобы получить размер.

В этой статье показано, как преобразовать FlowDocument в FormattedText. Я также пишу простой пример, используя Класс FlowDocumentExtensions в этой статье.

    public Window2()
    {
      InitializeComponent();

      StackPanel layoutRoot = new StackPanel();
      RichTextBox myRichTextBox = new RichTextBox() { Width=20};

      this.Content = layoutRoot;
      layoutRoot.Children.Add(myRichTextBox);

      myRichTextBox.Focus();
      myRichTextBox.TextChanged += new TextChangedEventHandler((o,e)=>myRichTextBox.Width=myRichTextBox.Document.GetFormattedText().WidthIncludingTrailingWhitespace+20);
    }


  public static class FlowDocumentExtensions
  {
    private static IEnumerable<TextElement> GetRunsAndParagraphs(FlowDocument doc)
    {
      for (TextPointer position = doc.ContentStart;
        position != null && position.CompareTo(doc.ContentEnd) <= 0;
        position = position.GetNextContextPosition(LogicalDirection.Forward))
      {
        if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
        {
          Run run = position.Parent as Run;

          if (run != null)
          {
            yield return run;
          }
          else
          {
            Paragraph para = position.Parent as Paragraph;

            if (para != null)
            {
              yield return para;
            }
          }
        }
      }
    }

    public static FormattedText GetFormattedText(this FlowDocument doc)
    {
      if (doc == null)
      {
        throw new ArgumentNullException("doc");
      }

      FormattedText output = new FormattedText(
        GetText(doc),
        CultureInfo.CurrentCulture,
        doc.FlowDirection,
        new Typeface(doc.FontFamily, doc.FontStyle, doc.FontWeight, doc.FontStretch),
        doc.FontSize,
        doc.Foreground);

      int offset = 0;

      foreach (TextElement el in GetRunsAndParagraphs(doc))
      {
        Run run = el as Run;

        if (run != null)
        {
          int count = run.Text.Length;

          output.SetFontFamily(run.FontFamily, offset, count);
          output.SetFontStyle(run.FontStyle, offset, count);
          output.SetFontWeight(run.FontWeight, offset, count);
          output.SetFontSize(run.FontSize, offset, count);
          output.SetForegroundBrush(run.Foreground, offset, count);
          output.SetFontStretch(run.FontStretch, offset, count);
          output.SetTextDecorations(run.TextDecorations, offset, count);

          offset += count;
        }
        else
        {
          offset += Environment.NewLine.Length;
        }
      }

      return output;
    }

    private static string GetText(FlowDocument doc)
    {
      StringBuilder sb = new StringBuilder();

      foreach (TextElement el in GetRunsAndParagraphs(doc))
      {
        Run run = el as Run;
        sb.Append(run == null ? Environment.NewLine : run.Text);
      }
      return sb.ToString();
    }
  }

Ответ 4

Я скопировал ваш код и его не в один столбец. У вас есть ширина где-то маленькая? Может быть, определен, например, для кода.

Ответ 5

Хм, у меня такая же проблема. Установка ширины в RichEdit фиксировала столбец с 1 буквой. Но когда нет установленной ширины, она отображает одну букву в строке. Я также установил цвет фона на что-то очень яркое, чтобы увидеть, что элемент управления занимает всю ширину страницы. (но с одним столбцом в нем.

Хммм

Ответ 6

Я заметил, что у меня была эта проблема, только когда мой стиль ScrollViewer по умолчанию явно установил HorizontalScrollBarVisibility = Hidden. Удаление этого сеттера (по умолчанию это значение "Скрыто" ) фиксировало проблему с одним столбцом для меня в моем RichTextBox.

Ответ 7

Только для записи, поскольку я думаю, что в этом потоке отсутствуют некоторые объяснения в соответствии с почему: реализация RichTextBox MeasureOverride похожа на это. Я не буду называть это ошибкой, может быть, просто плохой дизайн, оправданный тем фактом, что, как упоминалось выше, FlowDocument не из дешевых для измерения из-за его сложности. В нижней строке избегайте неограниченного ограничения ширины, привязывая MinWidth или оберните ее в ограничительный контейнер.

    /// <summary>
    /// Measurement override. Implement your size-to-content logic here.
    /// </summary>
    /// <param name="constraint">
    /// Sizing constraint.
    /// </param>
    protected override Size MeasureOverride(Size constraint)
    {
        if (constraint.Width == Double.PositiveInfinity)
        {
            // If we're sized to infinity, we won't behave the same way TextBox does under
            // the same conditions.  So, we fake it.
            constraint.Width = this.MinWidth;
        }
        return base.MeasureOverride(constraint);
    }