Occasionally the layout engine in WPF can arrange your elements in an unexpected pattern.
The Goal
Let’s say you want to have a simple form for data entry. You want some instruction text ( static multi-line) at the top of the form. You also want a multi-line TextBox for data entry. Sounds simple so far. You want the form to look like this.
Note: I’m not advocating the green and blue colors for your UI. I’m using them to help differentiate the label from the textbox.
Using a Label
If you come from a WinForms background the first control you are going to use for the static text is the Label.
<DockPanel HorizontalAlignment="Stretch" >
<Label
DockPanel.Dock="Top"
FontSize="16pt"
Foreground="Black"
Background="LightGreen"
HorizontalAlignment="Stretch"
>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. [text snipped]
</Label>
<Border BorderBrush="White" BorderThickness="4">
<TextBox
Name="MyRichTextBox"
FontSize="40pt"
Foreground="Black"
Background="LightBlue"
AcceptsReturn="True">
Type your text here...
</TextBox>
</Border>
</DockPanel>
This is what you see.
As you can see the instruction text is only one line high and the the text is truncated. In WPF, the label control is not your best choice for multiline text. The label does have one unique advantage over all the other controls though. You can specifiy an keyboard accelerator and a affiliated control. So you can link a label to a listbox, specify an accelerator key and when the user presses the key the focus moves to the affiliated control.
WPF has a rich assortment of classes for working with text. Here are a couple:
- Label
- TextBlock
- Textbox
- RichTextBox
- FlowDocument
TextBlock: Intended for showing single lines of formatted text. Textblock can show a mixture of font colors, styles, fontnames and sizes. It can show multiple lines, but will quickly show it’s limits.
TextBox: Holds more content than TextBlock. Shows unformatted text only. It has built in support for Cut, Copy and Paste.
RichTextBox: Holds more content than TextBlock, Similar to Textbox plus supports formatted text.
FlowDocument: Huge documents, supports formatted text, support for most document concepts like style, numbered lists, bullets, columns, embedded images.
Textblock
Since the label didn’t help us accomplish our goal lets look at the TextBlock. It looks like a good candidate. It has limited multi-line support and formatted text. Change the XAML to:
…
<DockPanel HorizontalAlignment=“Stretch“ >
<TextBlock
DockPanel.Dock=“Top“
FontSize=“16pt“
Foreground=“Black“
Background=“LightGreen“
HorizontalAlignment=“Stretch“
TextWrapping=“Wrap“
>
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. [text snipped]
</TextBlock>
…
Hmmm. Not exactly what we’re looking for. The TextBlock is centered by setting the HorizontalAlignment=“Stretch” attribute. But you can’t make it occupy the entire width of the DockPanel.
Now some of you are looking at this and thinking “That’s not right. I’ve seen TextBlock fill the space.”
You’re correct. But here is one of the quirks of WPF. The DockPanel is inside a Window element. If you change the Window element to Page this is what you’ll see.
Why does placing the TextBlock in a Window element have this odd behavior? I’m not sure. If you know why, add a comment to this post.
TextBox
If you change the TextBlock to a TextBox, it works correctly in both Page and Window. Since my goal didn’t specify that we wanted formatted text the TextBox is just what we need.
-Walt
Read Full Post »