Some tricks for working with WPF’s RichTextBox

I’ve been playing around with the RichTextBox, and as Richard points out, the free spell checking on WPF TextBoxes is really cool – especially for the “spelling challenged” such as myself.

 

The programming model for the WPF RichTextBox is quite a bit richer than the Windows Forms wrapper around the rich edit control – however it’s a bit more complex to work with. I’m still working out all the details of how to work with it, but I thought I’d write down what I’ve figured out:

 

To get to your actual content, you’ve gotta work with a Document object. This is the place where the actual text content can be manipulated. From here you can get what’s currently selected through the RichTextBox.Document.Selection property, or access “blocks” of text through the RichTextBox.Document.Blocks property.

 

Adding content to your RichTextBox in XAML:

In XAML. this is really easy… just add paragraphs and insert your formatting as you go.

 

          <RichTextBox IsSpellCheckEnabled="True">

        <FlowDocument>

          <Paragraph>

          This is a richTextBox. I can <Bold>Bold</Bold>, <Italic>Italicize</Italic>, <Hyperlink>Hyperlink stuff</Hyperlink> right in my document.

          </Paragraph>

        </FlowDocument>

      </RichTextBox>

 

Shrinking down the space between paragraphs:

Every time you have a newline in your text, this adds a new paragraph to your document. By default, there is a margin separating out the paragraphs, so it feels as if there is a blank line between paragraphs (I guess this keeps with the “P” html tag versus the “BR”?)

 

          <RichTextBox>

        <FlowDocument>

          <Paragraph>

            This is my first paragraph... see how there is...

          </Paragraph>

          <Paragraph>

            a huge amount of space between it and the second paragraph?

          </Paragraph>

        </FlowDocument>

      </RichTextBox>   

 

Anyways, in order to shrink down your spacing between paragraphs, you can make use of the styling features in WPF. You can say, “hey whenever I see a paragraph created within this rich textbox, reset its margins to 0”. The magic is done by a “Style” XAML tag, and by not specifying a particular key, and specifying a TargetType of Paragraph, all Paragraphs that are a child of the RichTextBox get the appropriate style. For more info on styles, the styles chapter of Chris Sells and Ian Griffith’s book is online.

 

         <RichTextBox>

        <RichTextBox.Resources>

          <Style TargetType="{x:Type Paragraph}">

            <Setter Property="Margin" Value="0"/>

          </Style>

        </RichTextBox.Resources>

        <FlowDocument>

          <Paragraph>

            This is my first paragraph... see how there is...

          </Paragraph>

          <Paragraph>

            a no space anymore between it and the second paragraph?

          </Paragraph>

        </FlowDocument>

      </RichTextBox>

 

So then the next question is how do I put plain text into the RichTextBox?     

Unless you want to replace the currently selected text (RichTextBox.Document.Selection.Text), you will need to access the RichTextBox.Document.Blocks collection to add more text to the textbox.

 

Here’s a quick code sample for replacing all text in a RichTextBox:

 

private void LoadTextFile(RichTextBox richTextBox, string filename) {

    richTextBox.Document.Blocks.Clear();

    using (StreamReader streamReader = File.OpenText(filename)) {

           Paragraph paragraph = new Paragraph();

           paragraph.Text = streamReader.ReadToEnd();

           richTextBox.Document.Blocks.Add(paragraph);

    }

}

 

How do I get Text back out of the RichTextBox?

To get the text back out of the RichTextBox, you need to use the TextRange class:

 

private string GetText(RichTextBox richTextBox) {

        // use a TextRange to fish out the Text from the Document

        TextRange textRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);

        return textRange.Text;

}

These were the next things I needed to know to use the control - when I find out more I'll keep you updated!

[Update: Part 2 here]