WPF数据模板中用于ListBox项的IsSelected触发器

59

我有一个列表框,它的ItemTemplate如下:

<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>

你可以看到ContentControl的Visibility被设置为collapsed。

我需要定义一个触发器,使得当ListItem被选中时,将Visibility设置为"Visible",但我无法想出解决方法。

有什么想法吗?

更新:当然我可以简单地复制DataTemplate并在相关的ListBox中添加触发器来使用其中的一个,但我想避免重复代码。

2个回答

130

你可以为ContentControl设置样式,这样当其容器(ListBoxItem)被选中时会触发一个触发器:

<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>

另一种方法是将触发器添加到模板本身并通过名称引用控件。我对这种技术不够熟悉,无法凭记忆输入代码并假设它能正常工作,但类似下面的示例:

<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>

2
哥们儿!太感谢了!虽然我没碰到这个问题,但是FindAncestor帮助我解决了一个困扰我两个小时的大问题!再次感谢。Jason - Jason Stevenson
1
设计者内容是什么?我正在尝试设置所选列表框项的背景(我使用内联数据模板)。当用户选择一个项目时,我希望它的背景不应变成蓝色,而应该与未选中的颜色相同。 - Shimmy Weitzhandler
只是想补充一下,在第二个示例中的DataTrigger绑定对我有很大帮助。谢谢! - NigelTufnel
2
DataTemplate.Triggers的例子非常有用!谢谢!专业提示:在<DataTemplate.Triggers>元素之前,您必须声明被“TargetName=”引用的控件。 - Wes
据我所知,使用“FindAncestor”是不好的做法,因为每次都应该有更直接的连接方式。 (目前我无法告诉您更好的解决方案) - Mechandrius

3

@Matt,谢谢你!!!

只需要添加一个触发器,当IsSelected == false时,现在它就像魅力一样工作了!

<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>


2
你不应该为“False”情况单独设置触发器。这由Triggers集合外的Visibility Setter处理。 - Matt Hamilton
9
只需在目标本身上指定一个值作为默认值,并使用触发器指定替代值。 - Drew Noakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接