WPF RichTextBox with no width set WPF RichTextBox with no width set wpf wpf

WPF RichTextBox with no width set


This is a confirmed bug with the WPF RichTextBox. To fix it, Bind the PageWidth of the FlowDocument to the RichTextBox width, i.e.

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

EDIT: Give the FlowDocument a name so that you can access it in the code behind and never new the flow document in codebehind.


Try binding the FlowDocument's width (one way) to the width of the container RichTextBox.

Worked for me...


The approach in this article worked for me:

WPF RichTextBox doesn't provide the functionality to adjust its width to the text. As far as I know, RichTextBox use a FlowDocumentView in its visual tree to render the Flowdocument. It will take the available space to render its content, so it won't adjust its size to the content. Since this is an internal class, it seems we cannot override the layout process to let a RichTextBox to adjust its size to the text.

Therefore, I think your approach is in the right direction. Unfortunelately, based on my research, there is no straightforward way to measure the size of the rendered text in a RichTextBox.

There is a workaround we can try. We can loop through the flowdocument in RichTextBox recursively to retrieve all Run and Paragraph objects. Then we convert them into FormattedText to get the size.

This article demonstrates how to convert a FlowDocument to FormattedText. I also write a simple sample using the FlowDocumentExtensions class in that article.

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