Layout
Taking another look at
Example 1-24 with the TextBlock and the Image as
content for the Button, we don't really have enough information to
place them inside the area of the button. Should they be stacked left-to-right
or top-to-bottom? Should one be docked on one edge and one docked to the other?
How are things stretched or arranged if the button resizes? These are questions
best answered with a panel.
A panel is a control that knows how
to arrange its content. WPF comes with the general-purpose panel controls
listed in Table 1-1.
Table 1-1. Main panel types
|
Panel type
|
Usage
|
DockPanel
|
Allocates an entire edge of
the panel area to each child; useful for defining the rough layout of simple
applications at a coarse scale.
|
StackPanel
|
Lays out children in a
vertical or horizontal stack; extremely simple, useful for managing small scale
aspects of layout.
|
Grid
|
Arranges children within a
grid; useful for aligning items without resorting to fixed sizes and positions.
The most powerful of the built-in panels.
|
Canvas
|
Performs no layout logicputs
children where you tell it to; allows you to take complete control of the
layout process.
|
1.4.1. Grid Layout
The most flexible panel by far is the grid,
which arranges content elements in rows and columns and includes the ability to
span multiple rows and columns, as shown in
Example 1-25.
Example 1-25. A sample usage of the Grid panel
<Window ...>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">A</Button>
<Button Grid.Row="0" Grid.Column="2">C</Button>
<Button Grid.Row="1" Grid.Column="0" Grid.RowSpan="2">D</Button>
<Button Grid.Row="1" Grid.Column="1">E</Button>
<Button Grid.Row="1" Grid.Column="2">F</Button>
<Button Grid.Row="2" Grid.Column="1">H</Button>
<Button Grid.Row="2" Grid.Column="2">I</Button>
</Grid>
</Window>
Example 1-25 used
the XAML property-element syntax to define a grid with three rows and three
columns inside the RowDefinition and ColumnDefinition elements.
In each element, we've specified the Grid.Row and Grid.Column
properties so that the grid knows which elements go where (the grid can have
multiple elements in the same cell). One of the elements spans two rows, and
one spans two columns, as shown in Figure
1-12.
Using the grid, we can be explicit about how we want to arrange
an image with a text caption, as in Example
1-26.
Example 1-26. Arranging an image and text in a grid
<Button Width="100" Height="100">
<Button.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="tom.png" />
<TextBlock
Grid.Row="1"
HorizontalAlignment="Center">Tom</TextBlock>
</Grid>
</Button.Content>
</Button>
Figure 1-13 shows
how the grid arranges the image and text for us.
Since we're just stacking one element on top of another, we
could've used the stack panel, but the grid is so general-purpose that many WPF
programmers find themselves using it for most layout configurations.
1.4.2. XAML Attached Property Syntax
You may have noticed that in setting up the Grid.Row and
Grid.Panel attributes of the Button elements, we used another
dotted syntax, similar to the property-element syntax, but this time on the
attribute instead of on the element. This is the attached-property
syntax and is used to set a property as associated with a particular element
e.g., a Buttonbut as defined by another elemente.g., a Grid.
The attached-property syntax is
used in WPF as an extensibility mechanism. We don't want the Button class
to have to know that it's being arranged in a Grid, but we do want to
specify Grid-specific attributes on it. If the Button were
being hosted in a Canvas, the Grid properties wouldn't make
any sense, so building Row and Column properties into the Button
class isn't such a great idea. Further, when we define our own custom panel
that the WPF team never considerede.g., HandOfCardswe want to be able
to apply the HandOfCards attached properties to arbitrary elements it
contains.
This kind of extensibility is what the attached-property syntax
was designed for, and it is common when arranging content on a panel.
For the nitty-gritty of layout, including the other panels and
text composition that I didn't show, you'll want to read
Chapter 2.
 |