WPF change visual state of datatemplate when selected in a listbox
Asked Answered
J

1

5

If I have a WPF ListBox which has a basic ItemTemplate that contains a custom user control, how can I tell the user control in the DataTemplate to change its visual state when its selected in the ListBox?

Thanks a lot for any help you can give

Jadda answered 7/1, 2011 at 4:20 Comment(0)
O
8

You can style the ListBoxItem to trigger on the IsSelected property. Here's an example:

and then you use it like this:

<ListBox ItemContainerStyle="{StaticResource yourListBoxItemStyle}">

or directly in the ListBox itself:

<ListBox.ItemContainerStyle>
    <Style TargetType=”ListBoxItem”>
        ...
    </Style>
</ListBox.ItemContainerStyle>

Edit:

Here is a complete example with both an ItemTemplate and an ItemContainerStyle that puts a semi-opaque layer on top of the selected item.

<Grid>
    <Grid.Resources>
        <x:Array Type="sys:String" x:Key="sampleData">
            <sys:String>Red</sys:String>
            <sys:String>Green</sys:String>
            <sys:String>Blue</sys:String>
        </x:Array>
        <DataTemplate x:Key="listBoxItem">
            <Rectangle Fill="{Binding}" Width="100" Height="100"/>
        </DataTemplate>
        <Style TargetType="ListBoxItem" x:Key="listBoxItemStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <Grid>
                            <ContentPresenter />
                            <Rectangle x:Name="Rectangle" Fill="Black" Opacity="0"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter TargetName="Rectangle" Property="Opacity"
                                    Value="0.5"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <ListBox
        ItemsSource="{StaticResource sampleData}"
        ItemTemplate="{StaticResource listBoxItem}"
        ItemContainerStyle="{StaticResource listBoxItemStyle}"
        />
</Grid>

Edit

After a comment, here is the version using a "unified" template:

<Style TargetType="ListBoxItem" x:Key="listBoxItemStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid>
                    <Rectangle Name="Rectangle" Fill="{Binding}" Width="100" Height="100" Opacity="1"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Rectangle" Property="Opacity"
                            Value="0.5"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Overact answered 7/1, 2011 at 5:7 Comment(8)
so are you saying NOT to use a ItemTemplate at all?Jadda
No, keep using your ItemTemplate. The ContentPresenter in the ControlTemplate in the example will end up "expanding" your ItemTemplate.Overact
ok thanks for the code, but I dont see how this will work if I want to change the property of the control (in your case the Rectangle class) within the DataTemplate as you cant access the control from the itemcontainer templateJadda
@Mark: normally these are separate so that selection logic doesn't have to be duplicated in every DataTemplate. But if you want to combine the two, then replace the ContentPresenter with your DataTemplate and then you can control the contents of the ListBoxItem directly.Overact
so in that case you would not be setting the ItemTemplate?Jadda
Right. If there is no ContentPresenter in the ControlTemplate, the ItemTemplate won't be used. I added an example.Overact
Thanks Rick! your help and prompt replies are greatly appreciated :)Jadda
If you put the ItemTemplate inside the ControlTemplate (replace ContentPresenter) you can't use a DataTemplate with DataType restriction. This essentially means you lose static analysis and all binding etc in both Visual Studio and Blend is harder. IMHO a major PITA.Mother

© 2022 - 2024 — McMap. All rights reserved.