28

次の 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 で作成すると、ウィンドウの幅を指定しないと、テキストが 1 列に 1 文字ずつ折り返されることがわかります。足りないものはありますか?コントロールの既知の欠陥である場合、回避策はありますか?

4

6 に答える 6

28

これは、WPF RichTextBox で確認されたバグです。これを修正するには、FlowDocument の PageWidth を RichTextBox の幅にバインドします。

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

編集: FlowDocument に名前を付けて、コード ビハインドでアクセスできるようにし、コード ビハインドでフロー ドキュメントを新しく作成しないようにします。

于 2010-04-14T00:48:58.920 に答える
10

FlowDocument の幅 (一方向) をコンテナの RichTextBox の幅にバインドしてみてください。

私のために働いた...

于 2009-03-03T17:07:39.463 に答える
7

この記事のアプローチは私のために働いた:

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();
    }
  }
于 2012-02-08T21:32:33.940 に答える
3

私はあなたのコードをコピーして貼り付けましたが、それは単一の列ではありません。幅が狭い場所はありますか? たとえば、コードビハインドで定義されている可能性があります。

于 2008-12-08T21:42:27.330 に答える
2

記録のために、このスレッドには理由に従っていくつかの説明が欠けていると思います: 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);
    }
于 2017-02-14T09:02:05.930 に答える