为什么这个触发器在它的值为 false 时更新?

Why is this trigger updating when its value is false?

目前我正在试验一个 ControlTemplate,它有一个 ListBox 和一个重叠的 Popup,一旦我将鼠标悬停在 ListBox 上就会触发。现在,当我将鼠标悬停在 ListBox 上时,它在 Popup 显示中运行良好。

但是,一旦我离开 ListBox 就像将鼠标悬停在 Popup 上一样,触发器似乎会再次更新 IsOpen-属性 并关闭 Popup。根据我的理解,触发器应该只在 IsMouseOver-属性 设置为 true 时触发,因此 Popup 应该保持打开状态(这是我的意图,因为它应该包含可点击的元素)。

我是否有逻辑错误或触发器在这种情况下究竟是如何工作的?

<ControlTemplate x:Key="SelectTargetsListBox">
    <Grid>
        <ListBox x:Name="PART_ListBoxBonusTargets" Height="200"
                 ItemsSource="{Binding Path=Targets}" />
        <Popup Name="PART_PopupListBoxBonusTargets" 
               PlacementTarget="{Binding ElementName=PART_ListBoxBonusTargets}" 
               Placement="Right" 
               VerticalOffset="-10" HorizontalOffset="-10" 
               PopupAnimation="Fade" AllowsTransparency="True" StaysOpen="True">
            <Border MinHeight="300" MinWidth="400" 
                    Background="{StaticResource BonusPopupBackgroundColor}" 
                    BorderBrush="{StaticResource BonusForegroundColor}" 
                    BorderThickness="3">
            </Border>
        </Popup>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger SourceName="PART_ListBoxBonusTargets" 
                 Property="IsMouseOver" Value="True">
            <Setter TargetName="PART_PopupListBoxBonusTargets" 
                    Property="IsOpen" Value="True" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

每次 IsMouseOver 属性 变化时触发。如果该值为真,它将触发您在 Trigger 中设置的更改,否则它将发送回初始状态。

正确的方法是通过事件调用来完成,我不知道这是否是最好的事件,但就像你有一个例子:

<ListBox MouseEnter="ListBox_MouseEnter" x:Name="PART_ListBoxBonusTargets" Height="200"
             ItemsSource="{Binding Path=Targets}" />

private void ListBox_MouseEnter(object sender, MouseEventArgs e) {
        e.Handled = true;
        PART_PopupListBoxBonusTargets.IsOpen = true;
    }

Do I have a logical error or how exactly does the trigger work in this case?

Popup的IsOpen属性只有在触发条件为真时才会为真。一旦触发条件变为假,IsOpen 属性 将重置为其默认值假。为什么?因为这是触发器在 WPF 中的工作方式。

请记住,XAML 是一种 标记 语言,即使您实际上可以用纯 XAML 实现某些东西,也不意味着您应该总是这样做。

像 C# 这样的编程语言比 XAML 更简洁、更具表现力,通常应该用于实现应用程序中的任何行为。

在这个示例中,以编程方式处理鼠标事件并显式将 Popup 的 IsOpen 属性 设置为 true/false 而不是尝试使用 XAML 会容易得多触发器。