WPF RichTextBox sans jeu de largeur

J'ai le code XAML suivant:

<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>

... Si vous créez cette fenêtre en XAML, vous pouvez voir que lorsque vous ne spécifiez pas de largeur pour la fenêtre, il encapsule le texte dans une seule colonne, une lettre à la fois. Est-il quelque chose que je suis absent? Si c'est une déficience connue dans le contrôle, y a-t-il une solution de contournement?

22
demandé sur Adrian Toman 2008-12-08 23:56:21

7 réponses

Essayez de lier la largeur du FlowDocument (à Sens Unique) à la largeur du conteneur RichTextBox.

Travaillé pour moi...

8
répondu azazeal 2009-03-27 16:41:52

Ceci est un bug confirmé avec le WPF RichTextBox. Pour le réparer, liez la PageWidth du FlowDocument à la largeur RichTextBox, c'est-à-dire

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

Modifier: Donnez un nom au FlowDocument afin que vous puissiez y accéder dans le code derrière et jamais nouveau le document de flux dans codebehind.

22
répondu lambinator 2012-09-28 19:16:12

L'approche dans Cet article a fonctionné pour moi:

WPF RichTextBox ne fournit pas la fonctionnalité pour ajuster sa largeur pour le texte. Pour autant que je sache, RichTextBox utilise un FlowDocumentView dans son arbre visuel pour rendre le Flowdocument. Il faudra disponibles espace pour rendre son contenu, de sorte qu'il ne sera pas ajuster sa taille à la contenu. Comme il s'agit d'une classe interne, il semble que nous ne pouvons pas remplacer le processus de mise en page pour laisser un RichTextBox pour ajuster sa taille le texte.

Par conséquent, je pense que votre approche est dans la bonne direction. Malheureusement, sur la base de mes recherches, il n'y a pas de moyen simple pour mesurer la taille du texte rendu dans un RichTextBox.

Il y a une solution de contournement que nous pouvons essayer. Vous pouvez parcourir le flowdocument dans RichTextBox récursivement pour récupérer tous les objets exécuter et Paragraphe. Ensuite, nous les convertissons en FormattedText pour obtenir la taille.

Cet article montre comment convertir un FlowDocument en FormattedText. J'écris aussi un échantillon simple en utilisant le Classe FlowDocumentExtensions dans cet 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();
    }
  }
6
répondu arolson101 2012-02-08 21:32:33

Je copie collé votre code et ce n'est pas dans une seule colonne, avez-vous une largeur quelque part qui est petite? Peut-être défini sur le code derrière par exemple.

2
répondu Artur Carvalho 2008-12-08 21:42:27

Juste pour l'enregistrement car je pense que ce fil manque quelques explications selon Pourquoi : L'implémentation de RichTextBox MeasureOverride est comme ça. Je n'appellerai pas cela un bug, peut-être juste un mauvais comportement de conception justifié par le fait que, comme mentionné ci-dessus, le FlowDocument n'est pas bon marché à mesurer en raison de sa complexité. Bottom line, évitez la contrainte de largeur illimitée en liant MinWidth ou en l'enveloppant dans un conteneur limitant.

    /// <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);
    }
1
répondu VeV 2017-02-14 09:02:05

Hmm j'ai le même problème. Définir une largeur sur le RichEdit fixe la colonne de 1 lettre. Mais quand il n'y a pas de largeur, il affiche une lettre par ligne. J'ai également mis la couleur d'arrière-plan à quelque chose de très flashy, pour voir le contrôle prend toute la largeur de la page. (mais avec un seul de ses colonnes.

Hmmm

0
répondu Tom Deleu 2009-01-08 20:12:53

J'ai remarqué que je n'avais ce problème que lorsque mon style ScrollViewer par défaut définissait explicitement HorizontalScrollBarVisibility = Hidden. La suppression de ce setter (la valeur par défaut est cachée de toute façon) a résolu le problème d'une seule colonne pour moi dans mon RichTextBox.

0
répondu patrickbadley 2014-03-25 18:10:59