You configure the column widths and row heights in a Grid using the ColumnDefinition and RowDefinition elements. There are three sizing options: fixed, automatic, and proportional.
Fixed sizing is the simplest to understand, but often requires the most effort to use, as you end up having to do all of the work yourself. You can specify the Width of a column or the Height of a row in device-independent pixels. (These are 1/96th of an inch. WPF's coordinate system is described in Chapter 13.) Example 3-8 shows a modified version of the column definitions in Example 3-7, specifying a fixed width for the first column.
Example 3-8. Fixed column width
<Grid.ColumnDefinitions> <ColumnDefinition Width="50" />
Figure 3-10. Grid layout
Example 3-8. Fixed column width (continued)
<ColumnDefinition /> </Grid.ColumnDefinitions>
Figure 3-11 illustrates the main problem with using fixed column widths. If you make the column too narrow, the contents will simply be cropped. Fixed widths and heights may seem to be an attractive idea because they give you complete control, but in practice they tend to be inconvenient. If you change the text or the font, you will need to modify the sizes to match. You will need to be flexible on layout if you want your application to fit in with the system look and feel, because the default font is not the same on all versions of Windows. Localization of strings will also require the sizes to be changed. (See Chapter 12 for more information about localization.) So in practice, fixed widths and heights are not what you will normally want to use. This is true not only with grids and text blocks. In general, you should try to avoid fixed sizes in WPF—the more you let the layout system do for you, the easier it is to adapt to localization, different screen sizes, and display orientations.
Protocok iHyperText Transfer Protocol
Type: HTML Document
The most appropriate sizing strategy for our label column will be automatic sizing. This tells the Grid to make the column wide enough to contain the widest element (i.e., to size to content). Example 3-9 shows a modified version of the column and row definitions from Example 3-7, specifying automatic width for the first column, and automatic heights for all of the rows.
Example 3-9. Automatic width and height
<Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions>
This is not quite right yet—as you can see from Figure 3-12, the Grid has not left any space around the text, so the results seem rather cramped. The solution is exactly the same as it was for the StackPanel—we simply use the Margin property on the TextBlock elements in the Grid to indicate that we want some breathing room around the text. The Grid will honor this, giving us the layout we require.
Protocol: ¡HycerText Transfer Protocol Figure 3-12. Automatic width and height
If the idea of adding a Margin attribute to every single element sounds tedious, don't worry. We can give all of the TextBlock elements the same margin by defining a style. Styles are discussed in Chapter 8. Example 3-10 does this to set a horizontal margin of five device-independent pixels, and a vertical margin of three.
Example 3-10. Applying a consistent margin with a style
ShowGridLines="True"> <Grid.Resources> <Style TargetType="TextBlock">
<Setter Property="Margin" Value="5,3" /> </Style> </Grid.Resources> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> ... as before
As Figure 3-13 shows, this provides the better-spaced layout we require.
Protocol: j H^perText Transfer Protocol
The final mechanism for specifying width and height in a Grid is the proportional method. This is sometimes called "star" sizing because of the corresponding XAML syntax. If you set the width or height of a column or row to be *, this tells the Grid that it should fill all the space left over after any fixed and automatic items have taken their share. If you have multiple items set to *, the space is shared evenly among them.
The default value for column width and row height is *, so you have already seen the effect of this. As Figure 3-10 shows, when we don't specify column widths or row heights, each cell ends up with exactly the same amount of space.
The star syntax is a little more flexible than this. Rather than dividing up space evenly among all the rows or columns marked with a star, we can choose a proportional distribution. Consider the set of row definitions in Example 3-11.
<Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="2*" /> <RowDefinition Height="1*" /> </Grid.RowDefinitions>
Here, the first row has been set to size automatically, and the other two rows both use proportional sizing. However, the middle row has been marked as 2*. This indicates that it wants to be given twice as much of the available space as the row marked with 1*. For example, if the grid's total height was 350, and the first row's automatic height came out as 50, this would leave 300 for the other rows. The second row's height would be 200, and the third row's height would be 100. Figure 3-14 shows how this grid looks for a couple of different heights; the filled-in background shows the size of the grid in each case. As you can see, the row with Auto height is the same in both cases. The two star-sized rows share out the remaining space, with the 2* row getting twice the height of the 1* row.
The numbers before the * specify relative sizes, not absolute sizes. If you modified the preceding example to use 6* and 3* instead of 2* and 1*, the result would be exactly the same. It's equivalent to saying that you want the rows to use six-ninths and three-ninths of the available space, instead of saying that you want them to use two-thirds and one-third—it's just two ways of expressing the same ratio.
These numbers are floating point, so you can specify noninteger sizes such as 2.5*. And if you specify just * without a number, this is equivalent to 1*.
If you are familiar with HTML, you may have been wondering whether you can use percentage sizes. You can't, but the star mechanism lets you achieve similar effects.
You may have noticed that for all three grid-sizing strategies, we used the Width and Height properties each time, although the property values looked quite different in each case. Width and Height are both of type GridLength. The GridLength type holds a number and a unit type. The number is stored as a Double and the unit type is represented by the GridUnitType enumeration.
For a fixed size, the unit type is Pixel. (As mentioned previously, in WPF pixel is really a device-independent unit, meaning 1/96th of an inch.) In XAML, this is indicated by providing just a number.* For automatic sizing, the unit type is Auto and no number is required. In XAML, this is indicated by the string "Auto". For proportional sizing, the unit type is Star. In XAML, this is indicated either by just * or a number and a star (e.g., 3.5*). Example 3-12 shows the C# equivalent of the row settings shown in XAML in Example 3-11.
Example 3-12. Setting row heights in code
RowDefinition r = new RowDefinition();
r.Height = new GridLength(0, GridUnitType.Auto);
g.RowDefinitions.Add(r); r = new RowDefinition();
r.Height = new GridLength(2, GridUnitType.Star);
g.RowDefinitions.Add(r); r = new RowDefinition();
r.Height = new GridLength(1, GridUnitType.Star);
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.