Reputation: 507
OK, I can't believe there is no online resources about this. I want to do a simple thing and change style of a ListBox
item when it's selected and it's parent ListBox
has lost focus.
We have been using VisualStateManager
for this purpose, but since there is overlapping in Selected
, SelectedFocused
and Focused
states, there were some bugs introduced when selecting items holding ctrl for example(wrong items appear selected). I decided to fix it using Trigger
s and found out that there seems to be no way of triggering when ListBox
lost focus.
My question is what is the right way of implementing this behavior, and please don't say "override SystemColors"...
EDIT:
OK, I have up-voted both answers but picked Viv's response because his answer makes it work exactly like original ListBox
while I don't have problems with mouse-over and other styles I already use. I have already seen usage of Selector
attached property, but never tried IsSelectionActive
, it worked like a charm. I would recommend going for triggers for this type of problem, although the VisualStateManager
is newer in WPF. I think there are clearly some problems with overlapping states that can be avoided.
Thanks again to Viv and Richard for providing great examples of 2 ways of implementing the solution for my problem.
Upvotes: 2
Views: 2612
Reputation: 17398
OK, I can't believe there is no online resources about this. I want to do a simple thing and change style of a ListBox item when it's selected and it's parent ListBox has lost focus.
guess your looking for a MultiTrigger
with IsSelected=true
and Selector.IsSelectionActive=false
?
so something like:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Margin="15">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Foreground"
Value="Blue" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected"
Value="true" />
<Condition Property="Selector.IsSelectionActive"
Value="false" />
</MultiTrigger.Conditions>
<Setter Property="Foreground"
Value="Red" />
</MultiTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem Content="A" />
<ListBoxItem Content="B" />
<ListBoxItem Content="C" />
</ListBox>
<ListBox Grid.Column="1"
Margin="15">
<ListBoxItem Content="A" />
<ListBoxItem Content="B" />
<ListBoxItem Content="C" />
</ListBox>
</Grid>
Now when an item in the left ListBox
is selected and then if the actual ListBox
looses focus, it would get a Red Foreground
like:
Foreground
is just an example, using the MultiTrigger
you can tweak the Style
as you see fit.
Upvotes: 6
Reputation: 4939
Here is a Style
for the ListBoxItem
that used the VisualStateManager
. It highlights the items in the manner that I would expect.
<Style TargetType="ListBoxItem">
<Setter Property="Foreground" Value="{DynamicResource ForegroundBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border"
Background="Transparent"
CornerRadius="3"
BorderThickness="1"
Padding="2">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="DodgerBlue"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="CornflowerBlue"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Upvotes: 3