WPF Trigger for IsSelected in a DataTemplate for ListBox items
Asked Answered
G

2

59

I have a listbox, and I have the following ItemTemplate for it:

<DataTemplate x:Key="ScenarioItemTemplate">
    <Border Margin="5,0,5,0"
            Background="#FF3C3B3B"
            BorderBrush="#FF797878"
            BorderThickness="2"
            CornerRadius="5">
        <DockPanel>
            <DockPanel DockPanel.Dock="Top"
                       Margin="0,2,0,0">
                <Button HorizontalAlignment="Left"
                        DockPanel.Dock="Left"
                        FontWeight="Heavy"
                        Foreground="White" />
                <Label Content="{Binding Path=Name}"
                       DockPanel.Dock="Left"
                       FontWeight="Heavy"
                       Foreground="white" />
                <Label HorizontalAlignment="Right"
                       Background="#FF3C3B3B"
                       Content="X"
                       DockPanel.Dock="Left"
                       FontWeight="Heavy"
                       Foreground="White" />
            </DockPanel>
            <ContentControl Name="designerContent"
                            Visibility="Collapsed"
                            MinHeight="100"
                            Margin="2,0,2,2"
                            Content="{Binding Path=DesignerInstance}"
                            Background="#FF999898">
            </ContentControl>
        </DockPanel>
    </Border>
</DataTemplate>

As you can see the ContentControl has Visibility set to collapsed.

I need to define a trigger that causes the Visibility to be set to "Visible"

when the ListItem is selected, but I can't figure it out.

Any ideas?

UPDATE: Of course I could simply duplicate the DataTemplate and add triggers to the ListBox in question to use either one or the other, but I want to prevent duplicating this code.

Grasmere answered 29/10, 2008 at 21:44 Comment(0)
N
130

You can style your ContentControl such that a trigger fires when its container (the ListBoxItem) becomes selected:

<ContentControl 
    x:Name="designerContent"
    MinHeight="100"
    Margin="2,0,2,2"
    Content="{Binding Path=DesignerInstance}"
    Background="#FF999898">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Setter Property="Visibility" Value="Collapsed"/>
            <Style.Triggers>
                <DataTrigger
                        Binding="{Binding
                            RelativeSource={RelativeSource
                                Mode=FindAncestor,
                                AncestorType={x:Type ListBoxItem}},
                                Path=IsSelected}"
                        Value="True">
                    <Setter Property="Visibility" Value="Visible"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

Alternatively, I think you can add the trigger to the template itself and reference the control by name. I don't know this technique well enough to type it from memory and assume it'll work, but it's something like this:

<DataTemplate x:Key="ScenarioItemTemplate">
    <DataTemplate.Triggers>
        <DataTrigger
                Binding="{Binding
                    RelativeSource={RelativeSource
                        Mode=FindAncestor,
                        AncestorType={x:Type ListBoxItem}},
                        Path=IsSelected}"
                Value="True">
            <Setter
                TargetName="designerContent"
                Property="Visibility"
                Value="Visible"/>
        </DataTrigger>
    </DataTemplate.Triggers>

    ...
</DataTemplate>
Narbonne answered 29/10, 2008 at 21:58 Comment(5)
Dude! Thank you so much! I wasn't having this issue but the FindAncestor helped me solve a big pain I had been banging my head for 2 hours! Thanks Again. JasonPinero
What's designerContent??? I am trying to set the selected listboxitem's background (I use an inline datatemplate). I want, that when the user selects an item it's background shouldn't become blue but should have the same color as unselected.Inoperable
Just wanted to add that the DataTrigger Binding in the second example helped me in a big way. Thanks!Petepetechia
The DataTemplate.Triggers example was really useful! Thanks! Pro-tip: You've got to declare the controls being referenced by "TargetName=" before the <DataTemplate.Triggers> element.Richert
As I read, using 'FindAncestor' is bad practice, since it will run searches everytime where a more direct connection should be possible. (At the moment I can't name you the better solution)Outrush
G
3

@Matt, Thank you!!!

Just had to add a trigger for IsSelected == false as well, and now it works like a charm!

<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
    <Setter Property="Visibility" Value="Collapsed"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
            <Setter Property="Visibility" Value="Visible"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="False">
            <Setter Property="Visibility" Value="Collapsed"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Grasmere answered 29/10, 2008 at 22:14 Comment(2)
You shouldn't have to have a separate trigger for the "False" case. That's handled by the Visibility Setter outside of the Triggers collection.Narbonne
Just specify one value as the default on the target itself, and use the trigger to specify the alternative value.Referee

© 2022 - 2024 — McMap. All rights reserved.