Many may be familiar with the ASP.NET GridView or DataGrid
control, a tabular control that accepts data that the control renders in a
table format. While the Grid element in Silverlight resembles the tabular
structure of these controls, this control is meant more for structuring than data
binding.
The Grid control is the core grid control for laying out
user interfaces. It's the control that appears by default when creating a
Silverlight user control. It's by no means the only control available, but it
is a very common one.
There are a few core properties to know about when setting
up this control:
·
ColumnDefinitions - Defines the columns that will appear in the grid
(1, 2, or X number of columns).
·
RowDefinitions - Defines the rows that will appear in the grid
(1, 2, or X number of rows).
·
Grid.Row - An attached property that specifies the row for the
control to appear on.
·
Grid.Column - An attached property that specifies the column for
the control to appear on.
·
Grid.RowSpan - An attached property that specifies how many rows
the targeted control should span onto.
·
Grid.ColumnSpan - An attached property that specifies how many
columns the targeted control should span onto.
If you aren't familiar with attached properties, the
Silverlight framework (and the .NET framework for WPF) made available a feature
called attached properties, which lets parent container controls attach
properties to its children for the purpose of supplying additional information
about something related to the control. In the case of the Grid, attached
properties let the parent know where to position the children (row/column), an
important feature.
In reality, attached properties are actually method calls to
a method within the Grid that lets this control know where to position its
children. All of the information related to the attached property is stored in
the extended object (the controls within the Grid) and is maintained by the
Silverlight framwork.
To start, a simplified grid is shown in listing 1.
Listing 1: Defining a simple Grid
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
This example sets up a Grid that has two rows and two
columns. Each row and column can have its width/height specified. For
instance, the RowDefinition supports the MinHeight, Height, and MaxHeight
properties that specify height of a row. These values can be left blank, or
the values could be defined as a numeric value (20) or a relative value (*, 2*,
etc.). The following are valid values:
Listing 2: Specifying Varying RowDefinition objects
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
The asterisk denotes relative widths in comparison to the
other rows/columns. The second row of the grid will be rendered double the
size as the first, or at least given double the height. However, this can
change because Silverlight adjusts the sizing of its children due to how the
control sizes are calculated by the Silverlight framework. This is where the
MinHeight and MaxHeight come into play. As each control is sized within the
container, Silverlight may adjust the contents, and will attempt to fit each
control within the desired height. If, for some reason, the content cannot fit
within the width or height, clipping may occur.
The column definition works the same way, except it
specializes in width. The same parameters for width can be applied: a numeric
value or a relative width, if any value is supplied. To add a control to a
column/row, use the following designation in Listing 3.
Listing 3: Adding a Control to the Grid
<Grid ..>
<TextBlock Text="First Name" Grid.Row="0" Grid.Column="0" />
<TextBox Name="FN" Grid.Row="0" Grid.Column="1" />
<TextBlock Text="Last Name" Grid.Row="1" Grid.Column="0" />
<TextBox Name="LN" Grid.Row="1" Grid.Column="1" />
<TextBox Name="Desc" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
This simple form uses the Grid control's attached property
mechanism to add the TextBlock or TextBox elements to the grid's markup. The
first TextBlock element positions itself in row 0 and column 0. To its right
is the first name TextBox element, with the last name elements appearing in the
next row. Note that the value zero is the default for the row and column; this
value doesn't need specified. For readability, I enter zeroes into the markup.
Sometimes, a control may need to span more than one row or
column. This could be for controls like a description element, where the user
needs more visibility of the control's content. In order to allow a TextBox to
span multiple columns, use the approach illustrated in Listing 3 by adding a
Grid.ColumnSpan attribute. This enables the control to flow across columns and
present itself without pushing column 1's content off of the page.
As long as the form only needs one element positioned within
a cell, this example works fine; the challenges come whenever the cell needs to
display more than one element. How can this be made possible?