You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Style的IsSelected触发器调用VisualStateManager.GoToState?

实现方法说明

WPF原生的Style Trigger无法直接调用VisualStateManager.GoToState,因为它仅支持设置属性、启动Storyboard等有限操作。要实现你要的效果,有两种常用方案:


方案一:使用Microsoft.Xaml.Behaviors.Wpf内置行为

这是最便捷的方式,需要先安装NuGet包Microsoft.Xaml.Behaviors.Wpf。

  1. 在XAML中添加行为命名空间:
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
  1. 在ListBoxItem的ControlTemplate里添加属性变化触发器,绑定IsSelected属性触发状态切换:
<Style TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid x:Name="rootGrid">
                    <!-- 你的VisualStateGroups定义 -->
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="PopupStates">
                            <VisualState x:Name="PopupClosed">
                                <Storyboard>
                                    <BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextPopup"
                                                                     Storyboard.TargetProperty="IsOpen">
                                        <DiscreteBooleanKeyFrame KeyTime="0:0:0.25" Value="False" />
                                    </BooleanAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="rootGrid"
                                                                   Storyboard.TargetProperty="(Panel.Background)">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{DynamicResource BrushIconComboBox_Popup_Closed_Background}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="PopupOpen">
                                <Storyboard>
                                    <BooleanAnimationUsingKeyFrames Storyboard.TargetName="ContextPopup"
                                                                     Storyboard.TargetProperty="IsOpen">
                                        <DiscreteBooleanKeyFrame KeyTime="0:0:0.25" Value="True" />
                                    </BooleanAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="rootGrid"
                                                                   Storyboard.TargetProperty="(Panel.Background)">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0.25" Value="{DynamicResource BrushIconComboBox_Popup_Open_Background}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <!-- 交互触发器:监听IsSelected变为True时切换状态 -->
                    <i:Interaction.Triggers>
                        <i:PropertyChangedTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
                            <i:GoToStateAction StateName="PopupClosed" />
                        </i:PropertyChangedTrigger>
                    </i:Interaction.Triggers>

                    <!-- 你的Popup控件 -->
                    <Popup x:Name="ContextPopup" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

方案二:自定义TriggerAction(无需第三方库)

如果不想引入第三方库,可以自己实现一个触发动作类:

  1. 编写自定义Action类:
using System.Windows;
using System.Windows.Interactivity;

public class GoToStateAction : TriggerAction<FrameworkElement>
{
    public static readonly DependencyProperty StateNameProperty =
        DependencyProperty.Register(nameof(StateName), typeof(string), typeof(GoToStateAction));

    public string StateName
    {
        get => (string)GetValue(StateNameProperty);
        set => SetValue(StateNameProperty, value);
    }

    protected override void Invoke(object parameter)
    {
        if (AssociatedObject != null && !string.IsNullOrEmpty(StateName))
        {
            VisualStateManager.GoToState(AssociatedObject, StateName, true);
        }
    }
}
  1. 在XAML中引用这个类,并在Style的Trigger里使用:
<!-- 先添加自定义类的命名空间,假设类在local命名空间下 -->
xmlns:local="clr-namespace:YourNamespace"

<Style TargetType="ListBoxItem">
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Trigger.EnterActions>
                <local:GoToStateAction StateName="PopupClosed" />
            </Trigger.EnterActions>
        </Trigger>
    </Style.Triggers>

    <!-- 你的ControlTemplate和VisualStateGroups定义 -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <!-- 模板内容 -->
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

内容的提问来源于stack exchange,提问作者cpdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:32:54