2008-12-08 13 views
20

Ich habe folgende XAML-Code:WPF RichTextBox ohne Breite gesetzt

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

... Wenn Sie das Fenster in XAML erstellen, können Sie sehen, dass, wenn Sie nicht festlegen, eine Breite Für das Fenster wird der Text in einer einzelnen Spalte umgebrochen. Gibt es etwas, das mir fehlt? Wenn es einen bekannten Mangel in der Kontrolle gibt, gibt es eine Problemumgehung?

Antwort

8

Versuchen der Flowdocument Breite Bindung (einfache Fahrt) auf die Breite des Behälters RichTextBox.

für mich gearbeitet ...

+4

Dieses Problem passiert mit mir immer wieder und wieder, also habe ich das übergeordnete Grid zu etwas wie "mainGrid" gekürzt und benannt und Width = "{Binding ElementName = mainGrid, Path = ActualWidth}" und Height = "{Binding ElementName = mainGrid, Path = ActualHeight} "um das gewünschte Verhalten zu erzwingen. – Michael

2

Ich kopiere Ihren Code eingefügt und es ist nicht in einer einzigen Spalte, Haben Sie eine Breite irgendwo, die klein ist? Vielleicht auf dem Code hinter zum Beispiel definiert.

+0

Einverstanden. Es muss etwas anderes passieren, vielleicht ein Stil für einen deiner Typen, der in deinem Projekt definiert ist. Das von Ihnen gepostete XAML-Snippet wird beispielsweise in XAML Cruncher angezeigt. –

0

Hmm Ich habe das gleiche Problem. Beim Festlegen einer Breite auf dem RichEdit wurde die 1-Buchstaben-Spalte korrigiert. Wenn jedoch keine Breite festgelegt ist, wird pro Zeile ein Buchstabe angezeigt. Ich setze auch die Hintergrundfarbe auf etwas sehr auffälliges, um zu sehen, dass das Steuerelement die ganze Breite der Seite einnimmt. (Aber mit nur einer Spalte in ihm.

Hmmm

20

Diese das ist ein Fehler mit dem WPF RichTextBox bestätigt. um es zu beheben, die Width des Flowdocument auf die RichTextBox Breite binden, dh

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

BEARBEITEN: Geben Sie FlowDocument einen Namen, damit Sie im Code darauf zugreifen können und das Flow-Dokument im Codebehind nicht neu erstellen.

+2

Wo wurde dieser Fehler bestätigt? Gibt es andere bekannte Problemumgehungen? Da ich mein FlowDocument dynamisch erstelle, funktioniert der PageWidth-Trick nicht für mich. – dthrasher

6

Der Ansatz in this article für mich gearbeitet:

WPF RichTextBox die Funktionalität nicht bieten seine Breite an den Text anzupassen. Soweit ich weiß, verwendet RichTextBox eine FlowDocumentView in seine visuelle Struktur, um das Flowdocument zu rendern. Es wird der verfügbare Speicherplatz benötigt, um seinen Inhalt zu rendern, sodass die Größe nicht an den Inhalt angepasst wird. Da dies eine interne Klasse ist, scheint es, dass wir den Layoutprozess nicht überschreiben können, damit eine RichTextBox ihre Größe an den Text anpassen kann.

Daher denke ich, dass Ihr Ansatz in die richtige Richtung ist. Unglücklicherweise, basierend auf meinen Nachforschungen, gibt es keinen einfachen Weg , um die Größe des gerenderten Textes in einer RichTextBox zu messen.

Es gibt eine Problemumgehung, die wir versuchen können. Wir können das flowdocument in RichTextBox rekursiv durchlaufen, um alle Run- und Paragraph-Objekte abzurufen. Dann konvertieren wir sie in FormattedText, um die Größe zu erhalten.

This article zeigt, wie Sie ein FlowDocument in formatierten Text konvertieren. Ich schreibe auch ein einfaches Beispiel mit der FlowDocumentExtensions-Klasse in diesem Artikel.

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

Ich habe 'FormatedTextWidth + 20' verwendet, um das Umbrechen zu verhindern. –

0

Ich bemerkte, dass ich nur dieses Problem hatte, als mein Standard-Scroll Stil explizit gesetzt HorizontalScrollBarVisibility = Verborgen. Das Entfernen dieses Setters (der Standardwert ist sowieso ausgeblendet) behebt das Problem mit der einzelnen Spalte für mich in meiner RichTextBox.

0

Nur für den Datensatz, wie ich denke, dieser Thread fehlt einige Erklärungen wie die warum: RichTextBox MeasureOverride Implementierung ist so. Ich werde das nicht als Bug bezeichnen, vielleicht nur ein schlechtes Designverhalten, das dadurch gerechtfertigt ist, dass das FlowDocument genau wie oben erwähnt aufgrund seiner Komplexität nicht billig zu messen ist. Bottom line, vermeiden Sie unbegrenzte Width Constraint durch Binden von MinWidth oder umbrechen Sie es in einem begrenzenden Container.

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

BTW, denken Sie daran, dass Sie in die Quelle der Framework-Hilfe schauen, um Verhaltensweisen zu verstehen, die auf den ersten Blick nicht so offensichtlich sind. Komm schon, wir alle wissen, dass es keine solchen Gedanken wie Bugs gibt ... Es sind nur Features :) lol. Und ein großes Lob an alle, die bei MS die Open Source von .NET gemacht haben! Machen Sie unser Leben so viel einfacher! – VeV