tags:

views:

16482

answers:

2

I need to change the DataTemplate for items in a ListBox depending on whether the item is selected or not (displaying different/more information when selected).

I don't get a GotFocus/LostFocus event on the top-most element in the DataTemplate (a StackPanel) when clicking the ListBox item in question (only through tabbing), and I'm out of ideas.

Thanks in advance.

+36  A: 

A full example can be found here on my new blog: Coding Context

The easiest way to do this is to supply a template for the "ItemContainerStyle" and NOT the "ItemTemplate" property. In the code below I create 2 data templates: one for the "unselected" and one for the "selected" states. I then create a template for the "ItemContainerStyle" which is the actual "ListBoxItem" that contains the item. I set the default "ContentTemplate" to the "Unselected" state, and then supply a trigger that swaps out the template when the "IsSelected" property is true. (Note: I am setting the "ItemsSource" property in the code behind to a list of strings for simplicity)

<Window.Resources>

<DataTemplate x:Key="ItemTemplate">
    <TextBlock Text="{Binding}" Foreground="Red" />
</DataTemplate>

<DataTemplate x:Key="SelectedTemplate">
    <TextBlock Text="{Binding}" Foreground="White" />
</DataTemplate>

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
    <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
        </Trigger>
    </Style.Triggers>
</Style>

</Window.Resources>
<ListBox x:Name="lstItems" ItemContainerStyle="{StaticResource ContainerStyle}" />
Micah
Nice example, excellent blog post too.
Scott A. Lawrence
@scott-a-lawrence Thanks!
Micah
Thank you, please include the <ListBox ItemContainerStyle=”{StaticResource ContainerStyle}” ItemsSource=”{Binding MyData}” /> in your post, so people don't have to search in your blog.
Shimmy
One problem I encountered with setting the ListBox's ContainerStyle is that it causes incompatibility with themes. I used your approach, but when I applied the a theme from the WPF Futures set the ListBoxItems had the default styling instead of the theme styling. In my case, black text on black background and general ugliness. I'm still searching for another approach, perhaps using DataTemplate triggers.
Benny Jobigan
Also, if you want your new ItemContainerStyle to be compatible with themes, you have to base it on the one from the theme. To do this, use `BasedOn="{StaticResource {x:Type ListBoxItem}}"` with ListBox. This also applies to other controls like TreeView.
Benny Jobigan
+2  A: 

It should also be noted, that the stackpanel isn't focuable, so it's never going to get focus (set Focusable=True if you /really/ want it focused). However, the key to remember in scenarios like this is that the Stackpanel is child of the TreeViewItem, which is the ItemContainer in this case. As Micah suggests, tweaking the itemcontainerstyle is a good approach.

You could probably do it using DataTemplates, and things such as datatriggers which would use the RelativeSouce markup extension to look for the listviewitem

dhopton