#1,049 – How the GridSplitter Behaves when Cells Use Star Sizing

Recall that a GridSplitter in its own column and with its HorizontalAlignment set to Center will resize columns on either side of it.  In the example below, columns 0 and 2 are resized, but the width of column 3 is not changed.

1049-001

1049-002

If all of the content columns are sized using star sizing, the GridSplitter will leave them as star sized, but change the coefficients to match the final size after moving the GridSplitter.  We can see this by dumping out the column widths before and after our sizing operation.

Before resizing, columns 0, 2 and 3 are all “1*” (or just “*”).  They take up equal space.

1049-003

After resizing, the coefficients change.  Columns are still proportionally sized, but the proportions are different.

1049-004

We can verify that the columns are sized proportionally by resizing the entire Grid (containing window).  The columns retain their post-GridSplitter relative sizes.

1049-005

#1,047 – Setting the Size of a Grid’s Rows or Columns from Code

There are three ways to set the size of a row or a column in a Grid:

  • Auto – set height/width to fit the size of the contained element
  • numeric value – explicitly set height/width to specified number of device independent units (1/96th in)
  • * or n* – distribute remaining space proportionately

You can set row or column sizes from code for all three of these methods.

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Set to Auto
            myGrid.RowDefinitions[0].Height = GridLength.Auto;

            // Set explicit size
            myGrid.RowDefinitions[1].Height = new GridLength(35.0, GridUnitType.Pixel);

            // Set star sizing (proportional)
            myGrid.RowDefinitions[2].Height = new GridLength(1.0, GridUnitType.Star);
            myGrid.RowDefinitions[3].Height = new GridLength(2.0, GridUnitType.Star);
        }

Before clicking the button, the row heights default to “*” (evenly spaced):
1047-001
After executing the code shown above, the Grid looks like this:
1047-002

#1,046 – Setting the Background Color of a Cell in a Grid

There are several different ways to set the background color of a cell within a Grid.  They include:

  • Setting the Background property of the element within a cell (e.g. a Label)
  • Including a Rectangle in the same cell as another element and setting its Fill property
  • Using a Border element and setting its Background property
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Larry" Margin="5" Background="Lavender"/>
        <Label Grid.Row="0" Grid.Column="1" Content="Moe" Margin="5" />

        <Rectangle Grid.Row="1" Grid.Column="0" Fill="Bisque"/>
        <CheckBox Grid.Row="1" Grid.Column="0" Margin="5" Content="Nose Tweak"
                  VerticalAlignment="Center"/>

        <Border Grid.Row="1" Grid.Column="1"  Background="MediumSpringGreen"
                CornerRadius="5" Margin="5">
            <Button Grid.Row="1" Grid.Column="1" Margin="5" Content="Do Eye Poke"
                    VerticalAlignment="Center"/>
        </Border>
    </Grid>

1046-001
 

#1,045 – Control Layering of Elements in a Grid Using ZIndex

If you have more than one user interface element in a particular grid cell, the elements are layered on top of each other.  Elements added earlier in XAML appear below (lower layer) than elements added later.

You can change the layering of the elements by changing the order in which they are added to the Grid.  You can also control the layering by giving each element a value for Panel.ZIndex.  Elements with higher values for ZIndex will appear to be on top of elements with lower values, regardless of the order in which they were added to the Grid.

In the example below, the Label appears on top of the Button because it has a higher value for ZIndex.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="Oops I'm in the same cell with a button !"
               Panel.ZIndex="2"/>
        <Button Content="Push Me" Width="100"
                Panel.ZIndex="1"/>
    </Grid>

1045-001

#1,044 – Placing More than One Element in a Grid Cell

There is nothing to prevent you from placing more than one element within a given cell in a Grid.  In the example below, the Button and the Label share the same cell.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Button Content="Push Me" Width="100" />
        <Label Content="Oops I'm in the same cell with a button !" />
    </Grid>

1044-001

By default, controls that share the same Grid cell are layered in the order in which they are added to the Grid.  Elements added earlier appear below elements added later.

If we reverse the order of the Button and Label elements in XAML, listing the Label first, it will appear under the Button.

1044-002

#885 – Wrapping a Grid in a ScrollViewer

Because the ScrollViewer control is a ContentControl, it can contain any single element.  It most often contains a single Panel, which in turn contains child elements.

Below is an example of a ScrollViewer that contains a Grid, which in turn contains a number of different elements.

    <ScrollViewer Margin="5" CanContentScroll="False"
                  HorizontalScrollBarVisibility="Auto">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Image Source="Augustus.jpg" Height="100" Margin="10"/>
            <Label Grid.Column="1" Content="Augustus - 63BC - 14AD" />

            <Image Grid.Column="2" Source="Tiberius.jpg" Height="100" Margin="10"/>
            <Label Grid.Column="3" Content="Tiberius - 42BC - 37AD"/>

            <Button Grid.Row="1" Content="Learn"
                    HorizontalAlignment="Center" VerticalAlignment="Center"
                    Padding="10,5"/>
            <Button Grid.Row="1" Grid.Column="2" Content="Learn"
                    HorizontalAlignment="Center" VerticalAlignment="Center"
                    Padding="10,5"/>
        </Grid>
    </ScrollViewer>

885-001
885-002

#578 – Grid Row and Column Size Use GridLength Object

When you create a Grid in XAML, you typically specify the rows and columns at design-time, along with the height of each row and width of each column.  Recall that there are three ways to set the height of a row or width of a column–explicit size, automatic or evenly distributed using remaining space in the Grid.

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="140"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

Within the RowDefinition and ColumnDefinition objects, the row height and column width are stored within a GridLength object.  GridLength has the three boolean properties IsAbsolute, IsAuto and IsStar indicating how the height or width is specified and then a Value property that contains the actual value.

 

#470 – Elements that Support RightToLeft Flow

Every FrameworkElement has a FlowDirection property that can be either LeftToRight (the default), or RightToLeft.  For panel elements that lay out a series of child elements, this property indicates in which direction the layout should be done.

The FlowDirection property is typically used for cultures where text flows from right to left, e.g. Arabic.  However, you can use this property whenever a right-to-left layout would make sense.

Below are some examples of elements that can use RightToLeft flow.

A Calendar control.

A DatePicker

A Menu, with MenuItem elements

A ListBox

A TreeView

A ProgressBar

A Grid

A StackPanel with Horizontal orientation

#457 – Use a GridSplitter to Let a User Change Row or Column Size in a Grid

Rows and columns in a Grid don’t normally change their size at runtime, unless the content of the Grid changes.  But you can allow a user to change the size of rows or columns by using a GridSplitter element.

You typically place a GridSplitter in its own row or column.  In the example below, the middle column contains a blue GridSplitter.  At runtime, a user can click and drag on this element to change the relative sizes of columns 0 and 2.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="Row 0 Col 0" Background="Azure" Grid.Row="0" Grid.Column="0" />
        <Label Content="Row 0 Col 2" Background="Lavender" Grid.Row="0" Grid.Column="2" />
        <Label Content="Row 1 Col 0" Background="Moccasin" Grid.Row="1" Grid.Column="0" />
        <Label Content="Row 1 Col 2" Background="Honeydew" Grid.Row="1" Grid.Column="2" />

        <GridSplitter Grid.Column="1" Grid.RowSpan="2" Width="3" Background="Blue"
                      VerticalAlignment="Stretch" HorizontalAlignment="Center" />
    </Grid>

Layout at startup:

User clicks and drags to the left:

Or drags to the right:

#456 – An Element in a Grid Can Span Multiple Rows or Columns

You can have child elements in a grid span multiple rows and/or multiple columns using the the Grid.RowSpan and Grid.ColumnSpan properties.

In the example below, the Image spans two rows and two columns and the TextBlock is located in a single row, but spans two columns.

    <Grid DataContext="{Binding GoodMovie}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Image Source="{Binding Image}" Grid.RowSpan="2" Grid.ColumnSpan="2"
               Width="142" Height="216" Margin="5"
               HorizontalAlignment="Center" VerticalAlignment="Center"/>

        <Label Content="{Binding Title}" FontWeight="Bold" Grid.Row="0" Grid.Column="2"/>
        <Label Content="{Binding Year}" Grid.Row="0" Grid.Column="3"/>

        <TextBlock Text="{Binding Summary}" Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"
                   TextWrapping="Wrap" Margin="8"/>

        <Label Content="Director:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right"/>
        <Label Content="{Binding Director}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Left"/>

        <Label Content="Actor:" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right"/>
        <Label Content="{Binding ActorLead}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left"/>

        <Label Content="Actress:" Grid.Row="4" Grid.Column="0" HorizontalAlignment="Right"/>
        <Label Content="{Binding ActressLead}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Left"/>
    </Grid>


You can see things a little better by turning on the grid lines.