WPF中RichTextBox高度自适应问题解决方法

最近做一个项目需要用到RichTextBox来显示字符串,但是不允许出现滚动条,在RichTextBox宽度给定的条件下,RichTextBox的高度必须正好显示内容,而不出现下拉滚动条。

这样就要计算要显示的文本的高度,在网上找了许久,其中使用了FormattedText类来计算文本的高度,发现FormattedText计算出的高度总是比RichTextBox需要的高度小。

在网上找到,可自定义一个控件,继承System.Windows.Controls.RichTextBox。

private void AdjustHeight() 

         { 

                 Rect rectStart = Document.ContentStart.GetCharacterRect(LogicalDirection.Forward); 

                 Rect rectEnd = Document.ContentEnd.GetCharacterRect(LogicalDirection.Forward); 

                 var height = rectEnd.Bottom - rectStart.Top; 

                 var remainH = rectEnd.Height / 2.0; 

                 var myHeight = Math.Min(MaxHeight, Math.Max(MinHeight, height + remainH)); 

                 this.Height = myHeight;



          }

        来计算Document的高度,但是在rectStart ,rectEnd 得到的值总是为Empty,没有办法来计算高度。后来发现只有在RichTextBox的IsArrangeValid值为True时,rectStart 、rectEnd 值才是有效的,必须放在

protected override void OnRender(DrawingContext drawingContext) 

           { 

                   base.OnRender(drawingContext); 

                   AdjustHeight();



           }

        这样才是有效的,但是包含这个自定义的RichTextBox的母控件必须是自定义的,按照如下重载MeasureOverride,ArrangeOverride方法,母控件对子控件进行二次测量、规划位置。重新对自定义的RichTextBox进行计算高度。

protected override Size MeasureOverride(Size availableSize) 

            { 

                    Size panelDesiredSize = new Size();



                    foreach (UIElement child in InternalChildren) 

                    { 

                            child.Measure(availableSize); 

                            panelDesiredSize = child.DesiredSize; 

                    }



                    return panelDesiredSize; 

            } 

            protected override Size ArrangeOverride(Size finalSize) 

            { 

                    foreach (UIElement child in InternalChildren) 

                    { 

                            double x = 10; 

                            double y = 5;



                            child.Arrange(new Rect(new Point(x, y), child.DesiredSize)); 

                    } 

                    return finalSize; // Returns the final Arranged size 

            }

这样实现的效果发现,UI运行比较慢。

后发现可以使用TextLine类来计算流文档的高度,关键代码如下:

public void Calculate() 

              {



                      var currentRendering = new FontRendering( 

    document.FontSize, 

    document.TextAlignment, 

    null, 

    document.Background, 

      new Typeface(document.FontFamily, document.FontStyle, document.FontWeight, document.FontStretch));





                      var textStore = new CustomTextSource(); 

                      textStore.Text = Content; 

                      textStore.FontRendering = currentRendering; 

                      var TextParagraphProperties = new GenericTextParagraphProperties(currentRendering);



                      System.Windows.Media.TextFormatting.TextFormatter 

          formatter = System.Windows.Media.TextFormatting.TextFormatter.Create(); 

                      TextLine myTextLine = null; 

                      int startPoint = 0; 

                      int RowCont = 0; 

                      do 

                      { 

                              myTextLine = formatter.FormatLine( 

          textStore, startPoint, document.MinPageWidth, TextParagraphProperties, null); 

                              //myTextLine.Draw(dc, new Point(0, RowCont * document.LineHeight), InvertAxes.None); 

                              startPoint = startPoint + myTextLine.Length; 

                              RowCont++; 

                      } while (startPoint < Content.Length); 

                      this.Height = Math.Max(RowCont * document.LineHeight, miniHight); 

              }

这个方法,可以在任何地方被正确的执行。一般可以在RichTextBox自定义控件的构造函数中调用,设定RichTextBox的高度。

关于TextLine 的使用,可以参考http://www.cnblogs.com/Clingingboy/archive/2010/12/03/1895326.html

最后RichTextBox实现的效果相当的好:

WPF中RichTextBox高度自适应问题解决方法

你可能感兴趣的:(高度自适应)