Reputation: 1386
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, would 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>
Upvotes: 0
Views: 295
Reputation: 1246
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.
Upvotes: 1
Reputation: 69985
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.
Upvotes: 0