#474 – Hiding a ComboBox Selection Highlight When the Mouse Moves off Item

By default, when you have a ComboBox open in WPF, a highlight is shown as you hover over different items in the ComboBox.

The last item that you hovered over with the mouse will remain selected even if you move the mouse off of the ComboBox.

If you’d rather have an item selected in the ComboBox only when you hover over it, you can modify the ItemContainerStyle for the ComboBox.

You can use Blend to make a copy of the existing template and then make changes to the copy.  In the template, you’ll find a trigger that sets the background of the ComboBoxItem when the IsHighlighted property is true.  You can change this to a MultiTrigger that also checks IsMouseOver.

<MultiTrigger>
    <MultiTrigger.Conditions>
        <Condition Property="IsHighlighted" Value="true"/>
        <Condition Property="IsMouseOver" Value="true"/>
    </MultiTrigger.Conditions>
    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</MultiTrigger>

#473 – Positioning Child Elements in a Canvas

Child elements are position in a Canvas panel by specifying the location of the child element in WPF units.

You can position all elements by specifying values for Left and Top properties only.  This will position each element relative to the upper left corner of the container.

These child elements will then retain the same position from the upper left corner of the container as it is resized.

You can specify a child element’s position relative to any of the four corners of the container, depending on which two of the four positioning properties you specify.  Child elements will then retain their position relative to that corner as the container is resized.

  • Left/Top – upper left corner
  • Right/Top – upper right corner
  • Right/Bottom – lower right corner
  • Left/Bottom – lower bottom corner
    <Canvas>
        <Button Content="Left=10,Top=10" Canvas.Left="10" Canvas.Top="10"/>
        <Button Content="Right=10,Top=10" Canvas.Right="10" Canvas.Top="10"/>
        <Button Content="Right=10,Bottom=10" Canvas.Right="10" Canvas.Bottom="10"/>
        <Button Content="Left=10,Bottom=10" Canvas.Left="10" Canvas.Bottom="10"/>
    </Canvas>


#472 – UniformGrid Defaults to Being Square

You typically set the number of rows and columns for a UniformGrid using the Rows and Columns properties.  You can also omit these properties and the UniformGrid will set the number of rows and columns based on the number of child elements.

The UniformGrid will attempt to create a square layout by automatically setting the number of rows and columns as listed below:

  • 1 element – 1 row, 1 column
  • 2-4 elements – 2 rows, 2 columns
  • 5-9 elements – 3 rows, 3 columns
  • 10-16 elements – 4 rows, 4 columns
  • Etc.

Notice that the UniformGrid in this situation will always have the same number of rows as columns.

    <UniformGrid>   <!-- No Rows/Columns specified -->
        <Label Content="1st" Background="AliceBlue" />
        <!-- Etc -->
    </UniformGrid>
</UniformGrid>





#471 – How FlowDirection Works with the Image Element

Unlike other elements, the Image control will not inherit it’s parent’s value of FlowControl.  However, you can explicitly set FlowControl for an Image to RightToLeft, which will flip the image horizontally.

    <StackPanel Orientation="Horizontal">
        <Image Source="Images\BestYears.jpg" Margin="5"/>
        <Image Source="Images\BestYears.jpg" Margin="5" FlowDirection="RightToLeft"/>
    </StackPanel>

#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

#469 – Filling a UniformGrid from Right to Left

A UniformGrid will normally lay out its child elements from left to right, starting in the first row (top to bottom, left to right).  You can reverse the left-to-right behavior by using the FlowDirection property.

The default value for FlowDirection is LeftToRight.  If you specify a value of RightToLeft, the UniformGrid will fill child elements from right to left within each row.  (Rows are still filled from top to bottom).

<UniformGrid Rows="2" Columns="4" FlowDirection="RightToLeft">
    <Label Content="1" Background="AliceBlue"/>
    <Label Content="2" Background="Cornsilk"/>
    <Label Content="3" Background="DarkSalmon"/>
    <Label Content="4" Background="Gainsboro"/>
    <Label Content="5" Background="LightBlue"/>
    <Label Content="6" Background="MediumAquamarine"/>
    <Label Content="7" Background="MistyRose"/>
</UniformGrid>

#468 – FirstColumn Property Allows Blank Cells in a UniformGrid

A UniformGrid will contain child elements in the order in which they appear in the XAML file where the UniformGrid is defined.  They will be placed into the first row of the UniformGrid (left to right) until the row fills up and then being filling the second row.

Child elements will normally appear starting in the first column of the first row.  You can instead have the first child appear in a different column by specifying a value for the FirstColumn property.  This property indicates the 0-based column number where the first child element will appear.  Child elements will then continue to fill in consecutive columns on the first row and then continue on the second row when the first fills up.

        <UniformGrid Rows="5" Columns="7" FirstColumn="3" >
            <Border BorderBrush="Black" BorderThickness="1"><Label Content="1"/></Border>
            <Border BorderBrush="Black" BorderThickness="1"><Label Content="2"/></Border>
            <Border BorderBrush="Black" BorderThickness="1"><Label Content="3"/></Border>
            <!-- etc -->
        </UniformGrid>

#467 – Use a UniformGrid for Evenly Spaced Rows and Columns

The UniformGrid layout panel is similar to a Grid, in that it lays child elements out in rows and columns.  But it’s different from a Grid in the following ways:

  • You don’t specify any size information for individual rows and columns
  • All columns are the same width
  • All rows are the same height
  • You specify the desired number of rows and columns
  • You don’t specify a row or column for child elements

Child elements are automatically placed into consecutive cells in the grid.  Each row is filled from left to right, starting with the first row.

    <UniformGrid Rows="2" Columns="3">
        <Label Content="1st" Background="Azure" />
        <Label Content="2nd" Background="Moccasin"/>
        <Label Content="3rd" Background="DarkSeaGreen"/>
        <Label Content="4th" Background="Violet" />
        <Label Content="5th" Background="Pink" />
    </UniformGrid>


#466 – Using a GridSplitter in Conjunction with a SharedSizeGroup

A GridSplitter allows a user to change the size of a row or column by dragging a visual splitter.  A SharedSizeGroup allows two rows or columns to automatically have the same size.  You can combine these concepts, allowing a user to change the size of one column and have another column automatically have the same size.

In the example below, the user can drag either splitter, but when dragging, the width of both left and right columns changes at the same time.

    <Grid Grid.IsSharedSizeScope="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A" Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition SharedSizeGroup="A" Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Label Content="Left" Background="Azure" Grid.Column="0"/>
        <Label Content="Middle" Background="Lavender" Grid.Column="2"/>
        <Label Content="Right" Background="Moccasin" Grid.Column="4"/>

        <GridSplitter Grid.Column="1" Width="8" Background="DarkSlateBlue"
                        HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
        <GridSplitter Grid.Column="3" Width="8" Background="DarkSlateBlue"
                        HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
    </Grid>

Window at startup:

User drags left splitter, which makes both left and right columns wider.

User drags right splitter and columns also resize together.

#465 – Using GridSplitters with Nested Grids

You can use GridSplitter elements in any Grid, including a Grid that’s nested inside another Grid.  This allows you to have GridSplitters that split elements within just a portion of the screen, as shown below.

In this example, the main grid has a vertical splitter between left and right sub-grids, each of which has a horizontal splitter between top and bottom panels.

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

        <!-- Sub-grid on left -->
        <Grid Grid.Column="0">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Label Content="Left, Row 0" Background="Azure" Grid.Row="0"/>
            <Label Content="Left, Row 2" Background="Lavender" Grid.Row="2"/>
            <GridSplitter Grid.Row="1" Height="8" Background="DarkSlateBlue"
                          HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
        </Grid>

        <!-- Sub-grid on right -->
        <Grid Grid.Column="2">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Label Content="Right, Row 0" Background="Moccasin" Grid.Row="0"/>
            <Label Content="Right, Row 2" Background="Honeydew" Grid.Row="2"/>
            <GridSplitter Grid.Row="1" Height="8" Background="DarkSlateBlue"
                          HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
        </Grid>

        <!-- Splitter between left/right sub-grids -->
        <GridSplitter Grid.Column ="1" Width="8" Background="DarkSlateBlue"
                      VerticalAlignment="Stretch" HorizontalAlignment="Center"/>
    </Grid>