WPF RichTextBox没有设置宽度

时间:2008-12-08 20:56:22

标签: 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中创建此窗口,您可以看到,当您没有为窗口指定宽度时,它会将文本包装在一个列中,一次一个字母。有什么我想念的吗?如果它是控制中已知的缺陷,是否有任何解决方法?

6 个答案:

答案 0 :(得分:23)

这是WPF RichTextBox的确认错误。要修复它,请将FlowDocument的PageWidth绑定到RichTextBox宽度,即

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

编辑: 为FlowDocument命名,以便您可以在后面的代码中访问它,并且永远不会在代码隐藏中新建流文档。

答案 1 :(得分:8)

尝试将FlowDocument的宽度(单向)绑定到容器RichTextBox的宽度。

为我工作......

答案 2 :(得分:6)

this article中的方法对我有用:

  

WPF RichTextBox不提供调整其宽度的功能   到文本。据我所知,RichTextBox使用FlowDocumentView   它的可视化树来渲染Flowdocument。这将是可用的   空间来呈现其内容,因此它不会调整其大小   内容。由于这是一个内部类,似乎我们无法覆盖   布局过程让RichTextBox调整其大小   文本。

     

因此,我认为您的方法是正确的方向。   不幸的是,根据我的研究,没有直截了当的方法   测量RichTextBox中渲染文本的大小。

     

我们可以尝试一种解决方法。我们可以遍历flowdocument   在RichTextBox中递归地检索所有Run和Paragraph对象。   然后我们将它们转换为FormattedText以获得大小。

     

This article演示了如何将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();
    }
  }

答案 3 :(得分:2)

我复制粘贴你的代码而不是一列,你有一个小的宽度吗?例如,可能在背后的代码上定义。

答案 4 :(得分:1)

我注意到,当我的默认ScrollViewer样式明确设置HorizontalScrollBarVisibility=Hidden时,我才遇到此问题。
删除此setter(默认值为Hidden)在我的RichTextBox中为我修复了单列问题。

答案 5 :(得分:1)

只是为了记录,因为我认为这个帖子缺少一些解释,根据为什么: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);
    }