Specifying the Selection Color, Content Alignment, and Background Color for items in a ListBox

This post covers some tips and tricks that people frequently ask concerning specifying the appearance of a ListBox. Here’s some things that someone, somewhere, might find useful:

Specifying the Selection Color

If you’ve ever tried the following, you know it won’t work.

      <Style TargetType="ListBoxItem">

        <Style.Triggers>

          <Trigger Property="IsSelected" Value="True">

            <Setter Property="Background" Value="LightGreen" />

          </Trigger>

        </Style.Triggers>

      </Style>

This doesn’t work because the control template of the ListBoxItem changes the background of an Border that is internal to the template, not the background of the ListBoxItem itself. The control template uses the color defined by SystemColors.HighlightBrush. Luckily, the SystemColors.HighlightBrush has a key associated with it, so you can create a Brush with its key set to SystemColors.HighlightBrushKey to change the color of a selected ListBoxItem:

      <Style TargetType="ListBoxItem">

        <Style.Resources>

          <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen"/>

        </Style.Resources>

      </Style>

 

You might be thinking, “That’s great, but when the control loses focus, the selection still turns to the default color (usually gray).” Never fear, the background for selected items in an inactive ListBox is specified by SystemColors.ControlBrush and you can use the SystemColors.ControlBrushKey to specify a different color. The following style causes the select items in a ListBox to be LightGreen when the ListBox has focus and LightBlue when it doesn’t have focus.

      <Style TargetType="ListBoxItem">

        <Style.Resources>

          <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightGreen"/>

          <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="LightBlue"/>

        </Style.Resources>

      </Style>

Aligning Content in a ListBox

Often you want the content of a ListBox to horizontally span the row. The Data Templating Overview discusses this, but it comes up frequently so it bears repeating. Suppose your ListBox is bound to a list of items to purchase. Perhaps you want the name of the item on the left and the price of the item below the name and to the far right. Your data template might look like this:

        <DataTemplate>

          <Grid>

            <Grid.RowDefinitions>

              <RowDefinition/>

              <RowDefinition/>

            </Grid.RowDefinitions>

            <TextBlock Text="{Binding XPath=@name}"/>

            <TextBlock Text="{Binding XPath=@price}"

                      Grid.Row="1" HorizontalAlignment="Right"/>

          </Grid>

        </DataTemplate>

This gives you the following:

As you can see, the TextBlock for the price is right-aligned, but it isn’t aligned with the edge of the ListBox. This is because the TextBlock is right-aligned with the Grid in the DataTemplate and the Grid sizes to its content To have the Grid span the width of the ListBox. Set the ListBox.HorizontalContentAlignment property to Stretch. Then the price will align to the right edge of the ListBox.

Making the Background Span the Entire Row

Setting the ListBox.HorizontalContentAlignment property to Stretch also allows the Background brush to paint the entire row of a ListBox. Suppose you want to bind the Background to a data source or use a data trigger to change the background of an item. The following data template changes the background on an item to red if it is sold.

        <DataTemplate>

            <Grid Name="grid1" Background="LightGreen">

            

             <Grid.RowDefinitions>

                <RowDefinition/>

                <RowDefinition/>

              </Grid.RowDefinitions>

             

              <TextBlock Text="{Binding XPath=@name}"/>

              <TextBlock Grid.Row="1"

                        Text="{Binding XPath=@price}"/>

            </Grid>

          <DataTemplate.Triggers>

            <DataTrigger Binding="{Binding XPath=@sold}" Value="true">

              <Setter TargetName="grid1" Property="Background" Value="Red"/>

            </DataTrigger>

          </DataTemplate.Triggers>

        </DataTemplate>

If you don’t set the HorizontalContentAlignmentProperty, the ListBox looks likes the following:

That’s probably not what you want. When ListBox.HorizontalContentAlignment equals to Stretch, the background paints the entire row.