【问题标题】:WPF RichTextBox with no width set没有设置宽度的 WPF RichTextBox
【发布时间】:2010-09-25 22:30:09
【问题描述】:

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

【问题讨论】:

    标签: wpf richtextbox


    【解决方案1】:

    我注意到只有当我的默认 ScrollViewer 样式显式设置 HorizontalScrollBarVisibility=Hidden 时我才会遇到这个问题。
    删除此设置器(默认值为 Hidden)为我修复了 RichTextBox 中的单列问题。

    【讨论】:

    • 遇到了完全相同的问题。 HorizontalScrollBarVisibility=Disabled 以外的任何值(或完全删除设置器)都会导致单列问题。
    【解决方案2】:

    仅作记录,因为我认为该线程缺少根据 why 的一些解释:RichTextBox MeasureOverride 实现就是这样。我不会称其为错误,也许只是一个糟糕的设计行为,正如上面提到的那样,FlowDocument 由于其复杂性而测量起来并不便宜。最重要的是,通过绑定 MinWidth 或将其包装在限制容器中来避免无限的 Width 约束。

        /// <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);
        }
    

    【讨论】:

    • 顺便说一句,请记住,查看框架的源代码有助于理解乍一看可能不那么明显的行为。来吧,我们都知道没有像错误这样的想法......它只是功能:) 哈哈。感谢 MS 的任何人使 .NET 开源成为现实!让我们的生活更轻松!
    【解决方案3】:

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

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

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

    【讨论】:

    • 这个错误是在哪里确认的?还有其他已知的解决方法吗?由于我动态构建了我的 FlowDocument,因此 PageWidth 技巧对我不起作用。
    • 我在执行此操作时遇到了可怕的性能问题,最终将我的RichTextBox 包装在一个网格中,以便我可以绑定到Grid.ActualWidth。希望我知道原因,但如果其他人遇到同样的性能问题,那我就解决了。
    【解决方案4】:

    this article 中的方法对我有用:

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

    因此,我认为您的方法是正确的。 不幸的是,根据我的研究,没有直接的方法 测量 RichTextBox 中呈现文本的大小。

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

    This article 演示如何将 FlowDocument 转换为 格式化文本。我还使用 该文章中的 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();
        }
      }
    

    【讨论】:

    • 我使用FormattedTextWidth + 20 来防止换行。
    【解决方案5】:

    尝试将 FlowDocument 的宽度(一种方式)绑定到容器 RichTextBox 的宽度。

    为我工作...

    【讨论】:

    • 这个问题一直在我身上发生,所以最终我只是屈服并将父网格命名为“mainGrid”之类的东西,并设置 Width="{Binding ElementName=mainGrid, Path=ActualWidth}"和 Height="{Binding ElementName=mainGrid, Path=ActualHeight}" 强制执行我想要的行为。
    【解决方案6】:

    我复制粘贴了您的代码,但它不在一个列中,您的某个地方的宽度是否很小?例如,可能在后面的代码中定义。

    【讨论】:

    • 同意。肯定有其他事情发生,也许是项目中定义的一种类型的样式。例如,您发布的 XAML 的 sn-p 在 XAML Cruncher 中显示得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 2018-03-06
    • 2013-05-17
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    • 2014-03-18
    相关资源
    最近更新 更多