#431 – Binding a Control’s Width to Its Height

Since you can bind a property of a control to a different property on that same control, you could bind a control’s width to its height to force the control to  always be square.

In the example below, the Button control’s width changes as the container is resized, since its HorizontalAlignment is set to Stretch.  The Height of the Button is then bound to the ActualWidth property, so that the height always matches the width.

    <StackPanel>
        <Button HorizontalAlignment="Stretch"
                Height="{Binding Path=ActualWidth, RelativeSource={RelativeSource Self}}"
                Content="Height set to Width"
                Margin="5" Padding="5"/>
    </StackPanel>


#430 – Setting Width and Height Using Different Units

When you specify the width or height of a control using a value that is a number, the value is interpreted in device independent units (1/96 in).  On a 96 dpi display, device independent units are equivalent to pixels.

<Button Width="80" Height="20" Content="80x20 units" HorizontalAlignment="Center" />

You can also add a suffix to the numeric value, indicating what type of units to use for the dimension.

  • px – device independent units (pixels on 96 dpi).  Same as including no suffix
  • in – inches
  • cm – centimeters
  • pt – points  (1 pt = 1/72 in)
    <StackPanel>
        <Button Width="100" Height="25" Content="100x25 units" HorizontalAlignment="Center" Margin="5"/>
        <Button Width="100px" Height="25px" Content="Also 100x25 units" HorizontalAlignment="Center" Margin="5"/>
        <Button Width="1.5in" Height="0.5in" Content="1-1/2 in x 1/2 in" HorizontalAlignment="Center" Margin="5"/>
        <Button Width="3cm" Height="0.5cm" Content="3 cm x 1/2 cm" HorizontalAlignment="Center" Margin="5"/>
        <Button Width="1in" Height="24pt" Content="1 in x 24 pt" HorizontalAlignment="Center" Margin="5"/>
    </StackPanel>

#429 – Child Element Properties that Affect Layout

Layout panels, like StackPanel and Grid, server as containers, containing child elements whose type is UIElement.  (In reality, most child elements derive from FrameworkElement, which in turns derives from UIElement).

Layout panels honor the following properties of their child elements.  These properties are all defined in FrameworkElement.

  • HorizontalAlignment – Horizontal alignment of an element (left, center, right, stretch)
  • VerticalAlignment – Vertical alignment of an element (top, center, bottom, stretch)
  • Margin – space between elements or between an element and the edge of the containing area
  • Width – width of element (in device indepent units, inches, cm, points, or auto)
  • Height – height of element (in device indepent units, inches, cm, points, or auto)
  • MinWidthminimum width of the element
  • MinHeightminimum height of the element
  • MaxWidthmaximum width of the element
  • MaxHeight – maximum height of the element

#428 – Setting Other Layout Properties from Within Blend

You can use the Properties window in Blend to set any of the properties of a control hosted in a layout container, including layout-related properties.

For example, assume that we have a Grid containing a couple of Button controls.  If you click on one of the buttons, you’ll see its properties in the Properties window to the right of the design surface.

You can see all of the layout related properties in the Layout panel, including height and width, row and column (where in the Grid is the button located), and alignment and margin properties.

You can click on the various horizontal and vertical alignment icons to change the alignment.

Less frequently used properties can be accessed by clicking on the little expander icon at the bottom of the layout panel.

The new panel contains properties like HorizontalContentAlignment, VerticalContentAlignment and Padding values.

#427 – Changing Margins from Within Blend

You can adjust margins by entering values directly in XAML.  You can also change margins by clicking and dragging on elements on the design surface in Blend.

Below is a Grid with two buttons:

    <Grid ShowGridLines="True" Background="Beige" Margin="10">
        <-- row/col defs here -->
        <Button Grid.Row="0" Grid.Column="0" Content="Dance" Margin="5" VerticalAlignment="Center"/>
        <Button Grid.Row="1" Grid.Column="1" Content="Play Ukulele" Margin="5" HorizontalAlignment="Center"/>
    </Grid>

Left-click on the Dance button on the design surface in Blend to see an indication of the margins.

Because the Dance button’s VerticalAlignment property is set to Center, it autosizes its height and the top/bottom margin values are not used.  The dashed lines above/below the button indicate that this distance is automatically set.

You can change the left or right margins by left-clicking on the left or right edges of the button and dragging.

You’ll see the margin value updated in the XAML.

#426 – Layout Panels Can Also Have Margins

You typically set margins on elements contained within a layout panel to create space between different elements and to create space between an element and the edge of the containing panel.

Here’s a Window containing a Grid (beige background), which contains some controls.  No margins have been set.

We can then specify a Margin value for the child elements within the Grid.  (Here, we set all margins to 5).  This creates space between each control and the cell in the Grid that it’s contained in.

We can also specify a Margin value for the Grid itself.  Doing so will create space between the Grid and the edges of its container, the Window.  In the example below, we specify a Margin of 10 for the Grid.  The background of the Window is set to blue, so that we can see the edges of the Grid.

 

 

#425 – SharedSizeGroup Allows Sharing Column Sizes Across Different Grids

You can use the SharedSizeGroup property of a ColumnDefinition to lead to consistent column sizes in a ListBox with a data template.  This works because each entry in the list has its own instance of a Grid and the column sizes are being shared across different grids.

As a more general example, we can share column sizes across two Grid controls hosted in the same window.

    <StackPanel Grid.IsSharedSizeScope="True">
        <Label Content="First grid:" />
        <Grid Margin="10" ShowGridLines="True" Background="AliceBlue">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Label Grid.Column="0" Content="{Binding Thing1}"/>
        </Grid>

        <Label Content="Second grid:" />
        <Grid Margin="10" ShowGridLines="True" Background="AliceBlue">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto" SharedSizeGroup="A"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Label Grid.Column="1" Content="{Binding Thing2}"/>
        </Grid>

        <Button Margin="10" Content="Change Thing1" Click="Button_Click" />
    </StackPanel>

We share size between the first column in the first grid and the second column in the second grid, since they use the same value for SharedSizeGroup.

After adding characters to Thing1:

#424 – Getting Data-Bound Items in a ListBox to Be a Consistent Size

I demonstrated earlier how to add some rich content to a ListBox using data binding.

The problem with this is that the items don’t line up vertically.  We use several StackPanel elements in the data template, which autosize to fit their content.  We’d like them to autosize, but to use that same size across all rows, for each column.

We can share sizes between entries using the Grid.IsSharedSizeScope and SharedSizeGroup properties.

        <ListBox ItemsSource="{Binding MovieList}" SnapsToDevicePixels="True"
                 Grid.IsSharedSizeScope="True">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="0,0,0,5">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Col1"/>
                            </Grid.ColumnDefinitions>
                            <Image Source="{Binding Image}" />
                        </Grid>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Col2"/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Orientation="Vertical">
                                <Label Content="{Binding Title}" FontWeight="Bold"/>
                                <Label Content="{Binding Year}"/>
                            </StackPanel>
                        </Grid>

                        <Border BorderBrush="Black" BorderThickness="0.5"/>

                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="Col3"/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Orientation="Vertical">
                                <Label Content="Actors:"/>
                                <Label Content="{Binding ActorLead}" Margin="10,0"/>
                                <Label Content="{Binding ActressLead}" Margin="10,0"/>
                            </StackPanel>
                        </Grid>

                        <Border BorderBrush="Black" BorderThickness="0.5"/>

                        <StackPanel Orientation="Vertical">
                            <Label Content="Director:"/>
                            <Label Content="{Binding Director}" Margin="10,0"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

#423 – Setting Maximum Height and Width for Rows and Columns in a Grid

In the same way that you can set minimum height and width of rows and columns in a Grid, you can also set the maximum height or width.

You set the maximum height of a row in a Grid using the MaxHeight property of a RowDefinition element.  You set the maximum width of a column by using the MaxWidth property of a ColumnDefinition element.

    <Grid ShowGridLines="True">
    	<Grid.RowDefinitions>
    		<RowDefinition Height="Auto" />
    		<RowDefinition Height="Auto"/>
    		<RowDefinition Height="Auto"/>
    		<RowDefinition Height="Auto"/>
    	</Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" MaxWidth="20"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*" MaxWidth="80"/>
        </Grid.ColumnDefinitions>


#422 – Setting Minimum Height and Width on Rows and Columns in a Grid

You can set a minimum height for a row in a Grid using the MinHeight property.  You can also set the minimum width of a column using the MinWidth property.

In the example below, we set the minimum height of the first column, even though its Width is also set to Auto.  We also set the minimum of the 4th column, whose width is set to 1* (the same width as the 3rd column).

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

When the application starts, the first column is already wider than its elements, because of its minimum width.  The 4th column is set to the same width as the 3rd, both of which are larger than the 4th column’s minimum width.

As we make the window narrower, the 4th column eventually reaches its minimum width and will not become any narrower.