Change the Selected Color Listbox

2019-01-25 22:21发布

问题:

I want to change the Selected Background and have it display a gradient with round corners. I've searched Google and found that some people do change the selected color by overriding the default color. Is there any way I can do this? I was thinking is there any way to display a round cornered border as the background when an item is selected?

回答1:

Here is the default style for a ListBoxItem (which is what we want to change). This style can be "retrieved" if you are using Expression Blend 4 by right clicking on a listboxitem in the Objects and Timelines control.

<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
    <Setter Property="Padding" Value="2,0,0,0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}" 
                Background="{TemplateBinding Background}" 
                Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"
                >
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="Selector.IsSelectionActive" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Let's pull out some important parts so that you learn to do this yourself.

<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">

This is the start of the Style declaration. We've given it a x:Key so it can be retrieved from a resource dictionary, and we've set the TargetType for ListBoxItem.

Now, we want to look for the portion of the style that we want to change. In this case, we're going to go down and look for a section of the style that is a MultiTrigger on the new ControlTemplate.

<MultiTrigger>
<MultiTrigger.Conditions>
        <Condition Property="IsSelected" Value="true"/>
        <Condition Property="Selector.IsSelectionActive" Value="false"/>
    </MultiTrigger.Conditions>
    <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>

This MultiTrigger needs 2 properties to match the values in order to be activated. This trigger, when activated, will change the background color to Value="..." and the foreground color to Value="...". In order to get a gradient background, we need to change the value in the Background Value="..." to a different brush. Let's create a quick little gradient brush (very colorful one too!)

<LinearGradientBrush x:Key="GradientBrush" StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="Red" Offset="0.25" />
      <GradientStop Color="Blue" Offset="0.75" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>

So now let's apply this to the Background of this trigger.

<Setter Property="Background" TargetName="Bd" Value="{StaticResource GradientBrush}"/>

Now, when this style is applied to the ListBoxItem, and the ListBoxItem IsSelected = True (and Selector.IsSelectionActive = false) you'll see a gradient background on the listboxitem.

Now, you also wanted rounded corners. If we go way up to the top of the ControlTemplate, we'll see a border declaration.

<Border x:Name="Bd"

In that declaration, we want to add a CornerRadius attribute to get the corners rounded on the ListBoxItem.

CornerRadius="5"

And now, you should be able to create a corner radius, linear gradient background listboxitem. I hope that you'll be able to carry on from here on your own.



回答2:

I have an example on my blog here. It overrides the ControlTemplate and the colors it uses also.