Taking another look at Example 1-22 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 will things be 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 following general-purpose panel controls:
Arranges content by position and size with no automatic rearrangement when the Canvas is resized DockPanel
Arranges content according to the edge that each piece of content "docks" to, except for the last, which fills the remaining area
Arranges content in rows and columns as specified by the developer
Arranges content top to bottom or left to right according to the orientation of the panel UniformGrid
Arranges content in a grid with the same number of rows and columns generated as needed to display the content
Arranges things in a horizontal row until the next item won't fit, in which case it wraps to the next row
The most flexible panel by far is the grid, which arranges content elements in rows and columns, including the ability to span multiple rows and/or multiple columns, as shown in Example 1-23.
<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="l" Grid.Column="0" Grid.RowSpan="2">D</Button> <Button Grid.Row="l" Grid.Column="l">E</Button> <Button Grid.Row="l" Grid.Column="2">F</Button> <Button Grid.Row="2" Grid.Column="l">H</Button> <Button Grid.Row="2" Grid.Column="2">I</Button> </Grid>
Example 1-23 used the XAML property element syntax to define a grid with three rows and three columns inside the RowDefinition and ColumnDefinition elements. On 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-13.
Figure 1-13. An example Grid panel in action
Using the grid, we can be explicit about how we want to arrange an image with a text caption (Example 1-24).
<Button Width="100" Height="100"> <Button.Content> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Image Grid.Row="0" Source="tom.png" /> <TextBlock Grid.Row="1"
HorizontalAlignment="Center">Tom</TextBlock> </Grid> </Button.Content> </Button>
Figure 1-14 shows how the grid arranges the image and text for us.
Because 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.
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 it is used to set a property as associated with the particular element (e.g., a Button), but as defined by another element (e.g., a Grid).
Figure 1-14. A grid arranging an image and a text block
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 was 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 considered (e.g., HandOfCards), we want to be able to apply the HandOfCards-related 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 that I didn't show, you'll want to read Chapter 3.
Was this article helpful?
What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.