views:

111

answers:

1

I have a style defined for my ListBoxItems with a trigger to set a background color when IsSelected is True:

    <Style x:Key="StepItemStyle" TargetType="{x:Type ListBoxItem}">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Border Name="Border" Padding="0" SnapsToDevicePixels="true">
                        <ContentPresenter />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="#40a0f5ff"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

This style maintains the selected item even when the ListBox and ListBoxItem loses focus, which in my case is an absolute must. The problem is that I also want the ListBoxItem to be selected when one of its TextBox's child gets focused. To achieve this I add a trigger that sets IsSelected to true when IsKeyboardFocusWithin is true:

<Trigger Property="IsKeyboardFocusWithin" Value="True">
    <Setter Property="IsSelected" Value="True" />
</Trigger>

When I add this trigger the Item is selected when the focus is on a child TextBox, but the first behaviour disappears. Now when I click outside the ListBox, the item is de-selected.

How can I keep both behaviours?

+2  A: 

When your listbox looses focus, it will set selected item to null because of your trigger. You can select on focus using some code behind that will not unselect when you loose focus.

XAML:

<Window x:Class="SelectedTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">

    <StackPanel>
        <TextBox Text="Loose focus here" />
        <ListBox Name="_listBox" ItemsSource="{Binding Path=Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" GotFocus="OnChildGotFocus">
                        <TextBox Text="{Binding .}" Margin="10" />
                        <TextBox Text="{Binding .}" Margin="10" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="SnapsToDevicePixels" Value="true"/>
                    <Setter Property="OverridesDefaultStyle" Value="true"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Border Name="Border" SnapsToDevicePixels="true" Background="Transparent">
                                    <ContentPresenter />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="Border" Property="Background" Value="Red"/>
                                    </Trigger>                                   
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </StackPanel>
</Window>

Code behind:

private void OnChildGotFocus(object sender, RoutedEventArgs e) 
{   
   _listBox.SelectedItem = (sender as StackPanel).DataContext; 
}
Wallstreet Programmer
Thanks very much! That's exactly what I was looking for.
jpsstavares