简体   繁体   中英

Keeping coustum style of ListBoxItem when selected

I have a ListBox where the background color of the items are bound to some property of the entry:

<ListBox ItemsSource="{Binding ObservableCollectionOfFoos}" >
    <ListBox.ItemContainerStyle >
        <Style TargetType="ListBoxItem" >
            <Setter Property="Content" Value="{Binding SomePropertyOfFoo}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding AnotherPropertyOfFoo}" Value="true">
                    <Setter Property="Background" Value="Green" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

This works, but when I mouse over or select an item the background changes (unsurprisingly perhaps) to the default mouse over / selected color.

I'm new to WPF and I'm not sure I'm going about doing this kind of thing correctly, I thought maybe I need to use ItemContainerStyleSelector, but I'm confused as to how to use it, and it seems silly to have to create a class just for this small thing...

What I also thought was to create an IValueConverter from boolean to the color, and then bind though it without having to use DataTrigger as a different approach, woud that be more elegant? would that some how help me with this problem?

edit:

It would also be nice if I could change the background color of the selected item to a different color based on AnotherPropertyOfFoo, if it's not too much to ask

edit 2 (extension to comment on @Sheridan answer):

this does not work

    <ListBox>
        <ListBox.Items>
            <ListBoxItem>one</ListBoxItem>
            <ListBoxItem>two</ListBoxItem>
            <ListBoxItem>three</ListBoxItem>
            <ListBoxItem>four</ListBoxItem>
        </ListBox.Items>
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="Background" Value="Green" />
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red" />
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
                </Style.Resources>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>

You can also override Template of ListBoxItem, extract default using blend and override or use some already mentioned here.

Edit

Actually it is not so hard to override Template :) and I guess it is most correct way to solve your problem. Try this ItemContainer style. It replaces default ListBoxItem style->Template. To see how does it work - in triggers you can change any property of listbox item.

 <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Padding" Value="2,0,0,0"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border Name="Border" Padding="2" SnapsToDevicePixels="true">
                                <ContentPresenter />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter TargetName="Border" Property="Background" Value="LightBlue"/>
                                </Trigger>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter TargetName="Border" Property="Background" Value="Blue"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="Gray"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.ItemContainerStyle>

The default style of ListBoxItem you can find here to make required modifications.

Try using this:

<ListBox ItemsSource="{Binding ObservableCollectionOfFoos}" >
    <ListBox.ItemContainerStyle >
        <Style TargetType="ListBoxItem" >
            <Setter Property="Content" Value="{Binding SomePropertyOfFoo}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding AnotherPropertyOfFoo}" Value="true">
                    <Setter Property="Background" Value="Green" />
                </DataTrigger>
            </Style.Triggers>
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
            </Style.Resources>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

The SystemColors.HighlightBrushKey represents the default background colour of the selected item in collection controls... here it is set to Transparent , but you can set it to which ever colour you prefer.

UPDATE >>>

This code works just fine... if you change the first SolidColorBrush in the Resources section to Red , then the selected item background colour will be Red . Your Binding of AnotherPropertyOfFoo will not affect the selected item as there is no relationship between the two. To achieve that, you can try this instead:

<ListBox ItemsSource="{Binding ObservableCollectionOfFoos}" >
    <ListBox.ItemContainerStyle >
        <Style TargetType="ListBoxItem" >
            <Setter Property="Content" Value="{Binding SomePropertyOfFoo}"/>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{Binding AnotherPropertyOfFoo}" />
                </DataTrigger>
            </Style.Triggers>
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
            </Style.Resources>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Now the selected item will get the background colour from the AnotherPropertyOfFoo property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM