StackPanel
StackPanel is a very
simple panel. It simply arranges its children in a row or a column. We've seen
it once already in
Example 2-1, but that was a somewhat unrealistic example. You will
rarely use StackPanel to lay out your whole user interface. It is at
its most useful for small-scale layoutyou use DockPanel or Grid
to define the overall structure of your user interface, and then StackPanel
to manage the details.
For example, we used DockPanel in
Example 2-4 for the basic layout of our documentation viewer. We will
now use StackPanel to arrange the contents of the search panel on the
left-hand side. The markup in Example
2-5 replaces the placeholder TextBlock that contained the text
"Search panel goes here."
Example 2-5. StackPanel search layout
<StackPanel DockPanel.Dock="Left" Orientation="Vertical"
Background="#ECE9D8">
<TextBlock>Look for:</TextBlock>
<ComboBox />
<TextBlock>Filtered by:</TextBlock>
<ComboBox />
<Button>Search</Button>
<CheckBox>Search in titles only</CheckBox>
<CheckBox>Match related words</CheckBox>
<CheckBox>Search in previous results</CheckBox>
<CheckBox>Highlight search hits (in topics)</CheckBox>
</StackPanel>
This first attempt is a particularly straightforward layoutwe
have simply provided a list of the controls.
Figure 2-8 shows the results.
This is approximately what we require, but there are a few rough
edges to the layout. The controls are all rather close to the edge of the
panel, and to each other. This makes the user interface feel rather cramped,
and it would look better with some breathing space.
This problem can be solved using the Margin property,
which is present on all WPF elements. It indicates the amount of space that
should be left around the edges of the element when it is laid out. The Margin
property is described in more detail in the "Common
Layout Properties" section, later in this chapter.
Example 2-6 shows the search StackPanel again, this time with Margin
specified for each of the elements.
Example 2-6. Adding space with Margin
<StackPanel DockPanel.Dock="Left" Orientation="Vertical"
Background="#ECE9D8">
<TextBlock Margin="3">Look for:</TextBlock>
<ComboBox Margin="3"/>
<TextBlock Margin="3">Filtered by:</TextBlock>
<ComboBox Margin="3"/>
<Button Margin="3,5">Search</Button>
<CheckBox Margin="3">Search in titles only</CheckBox>
<CheckBox Margin="3">Match related words</CheckBox>
<CheckBox Margin="3">Search in previous results</CheckBox>
<CheckBox Margin="3">Highlight search hits (in topics)</CheckBox>
</StackPanel>
Most of the controls have a uniform margin of 3. (Since only one
number has been specified, this applies to all sides.) The Button has
a horizontal margin of 3 and a vertical margin of 5. This leaves little more
space above and below the Button than the other elements in order to
make the UI look less cramped.
With these margins specified, the panel looks a lot less
crowded, as Figure 2-9 shows.
While this is an improvement, there is still one problem with this layout. The
Search button looks a little oddit is much wider than you would normally expect
a button to look.
The default behavior of a vertical StackPanel is to
make all of the controls the same width as the panel. (Likewise, a horizontal StackPanel
will make all of the controls the same height.) For the ComboBox controls,
this is exactly what we want. For the TextBlock and CheckBox controls,
it doesn't show that the controls have been stretched to be as wide as the
panel, because they only look as wide as their text makes them look. However, a
Button's visuals always fill its entire logical width, which is why
the button in Figure 2-9 is
unusually wide.
We would like the button to have a normal width, rather than
being stretched across the panel's whole width. This is done by setting the
button's HorizontalAlignment property to Left:
<Button Margin="3,5" HorizontalAlignment="Left">Search</Button>
HorizontalAlignment determines an element's horizontal
position and width in situations where the containing panel gives it more space
than it needs. The default is Stretch, meaning that if there is more
space available than the child requires, it will be stretched to fill that
space. The alternatives, Left, Right, and Center, do
not attempt to stretch the elementthese determine where the element will be
placed within the excess space, allowing the element to use its natural width.
Here we are using Left, meaning that the control will have its
preferred width and will be aligned to the left of the available space (Figure
2-10).
Note that HorizontalAlignment is only significant when
the chosen layout style means more space is available than is needed. This
happens with a vertical StackPanel, because the panel will typically
make sure it is wide enough for the widest element. If the elements have
different widths, this means that all but the widest will have more space than
they require, at which point HorizontalAlignment comes into play. This
does not occur in a horizontal StackPanel, because that will let each
control be exactly as wide as it wants to. However, in that case, it usually
sets the panel height to be large enough to accommodate the tallest control, at
which point the VerticalAlignment property becomes significant for all
the others.
Margin, HorizontalAlignment, and VerticalAlignment
are all examples of layout properties present on all elements, which are
honored by the built-in panel types where possible. (In certain cases, these
properties have no meaning and are therefore ignored. For example, the Canvas
always uses absolute positioning and allows its children to use their preferred
size, so the alignment properties do nothing.) A complete list of these
panel-independent layout properties is given in the "Common
Layout Properties" section later in this chapter.
The search panel is a relatively simple user interface, so the StackPanel
was able to meet all of its requirements. However, it is common to encounter
layout problems which are hard to address with either the StackPanel or
DockPanel. These are particularly common with dialog design, so we
will now create a Properties dialog for our documentation viewer using the Grid
panel.
 |