WPF中如何设置弹出控件自动隐藏?

How to set the popup control hide automatically in WPF?

如图所示,我希望在鼠标进入 ButtonOne 按钮时显示 "one" 弹出控件。当我将鼠标从 ButtonOne 移到 Button Two 时,"One" 弹出控件隐藏并显示 "Two"。当鼠标不在按钮或弹窗上时,弹窗控件自动隐藏。

我试过使用mouse_enter和mouse_leave事件,但是当鼠标在按钮上移动时,弹出控件会闪烁。当鼠标不在按钮或弹出控件上时,弹出控件不隐藏。

那么,如何解决这个问题?

XAML:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel>
        <Button Name="ButtonOne" Height="100" Width="100" HorizontalAlignment="Left" MouseEnter="Button_MouseEnter" MouseLeave="ButtonOne_MouseLeave">Button One</Button>
        <Button Name="ButtonTwo" Height="100" Width="100" HorizontalAlignment="Left" MouseEnter="Button_MouseEnter_1" MouseLeave="ButtonTwo_MouseLeave">Button Two</Button>
        <Popup Name="Pop1" StaysOpen="False" Placement="Right" PlacementTarget="{Binding ElementName=ButtonOne}" PopupAnimation="Fade" AllowsTransparency="True" MouseEnter="Pop1_MouseEnter" MouseLeave="Pop1_MouseLeave">
            <Border BorderBrush="Beige" BorderThickness="2" Background="White">
                <StackPanel>
                    <TextBlock Text="One"></TextBlock>
                    <Button Content="OneManagement"></Button>
                </StackPanel>
            </Border>
        </Popup>
        <Popup Name="Pop2" StaysOpen="False" Placement="Right" PlacementTarget="{Binding ElementName=ButtonTwo}"  PopupAnimation="Fade" AllowsTransparency="True">
            <Border BorderBrush="Beige" BorderThickness="2" Background="White">
                <StackPanel>
                    <TextBlock Text="Two"></TextBlock>
                    <Button Content="TwoManangement"></Button>
                </StackPanel>
            </Border>
        </Popup>
    </StackPanel>
</Grid>

隐藏代码:

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_MouseEnter(object sender, MouseEventArgs e)
    {
        Pop2.IsOpen = false;
        Pop1.IsOpen = true;
    }

    private void Button_MouseEnter_1(object sender, MouseEventArgs e)
    {
        Pop1.IsOpen = false;
        Pop2.IsOpen = true;
    }


    private void ButtonOne_MouseLeave(object sender, MouseEventArgs e)
    {
        Pop1.IsOpen = false;
    }

    private void ButtonTwo_MouseLeave(object sender, MouseEventArgs e)
    {
        Pop2.IsOpen = false;
    }

    private void Pop1_MouseEnter(object sender, MouseEventArgs e)
    {
        Pop1.IsOpen = true;
    }

    private void Pop1_MouseLeave(object sender, MouseEventArgs e)
    {
        Pop1.IsOpen = false;
    }

}

最好使用StaysOpen="False",这样当失去焦点时弹出窗口会自动关闭。你可以像下面这样使用

<Popup x:Name="myPopUp" StaysOpen="False">

如果您将 Pop1 StaysOpen 属性 设置为 False,弹出窗口打开的那一刻,ButtonOneMouseLeave 事件被触发,即使鼠标实际上仍在按钮上。之后,当弹出窗口仍处于打开状态时,您的按钮将不再触发 MouseEnterMouseLeave 事件。这是因为当 StaysOpen 为 false 时,Popup 控件 拦截所有 鼠标和键盘事件以确定这些事件之一何时发生在 Popup 控件之外。

因此,您可以将弹出窗口的 StaysOpen 属性 设置为 True:

<Popup Name="Pop1" StaysOpen="True" ...
<Popup Name="Pop2" StaysOpen="True" ...

然后,您按钮的 MouseLeave 事件处理程序可以检查鼠标离开的位置:

private void ButtonOne_MouseLeave(object sender, MouseEventArgs e)
{
    Point leavePoint = e.GetPosition(ButtonOne);
    if (leavePoint.X < ButtonOne.ActualWidth)
    {
        Pop1.IsOpen = false;
    }
}

private void ButtonTwo_MouseLeave(object sender, MouseEventArgs e)
{
    Point leavePoint = e.GetPosition(ButtonTwo);
    if (leavePoint.X < ButtonTwo.ActualWidth)
    {
        Pop2.IsOpen = false;
    }
}

通过检查离开位置,我们仅在鼠标通过弹出窗口位置以外的其他位置离开按钮时关闭弹出窗口(在本例中为按钮的右侧)。换句话说,对于这种情况,我们希望当鼠标从顶部、左侧和底部离开按钮时弹出窗口关闭,但如果鼠标从右侧离开按钮,我们希望弹出窗口保持打开状态。

随后,我们可以对弹出 MouseLeave 事件处理程序使用类似的逻辑:

private void Pop1_MouseLeave(object sender, MouseEventArgs e)
{
    Point leavePoint = e.GetPosition(ButtonOne);
    if (leavePoint.X > ButtonOne.ActualWidth)
    {
        Pop1.IsOpen = false;
    }
}

private void Pop2_MouseLeave(object sender, MouseEventArgs e)
{
    Point leavePoint = e.GetPosition(ButtonTwo);
    if (leavePoint.X > ButtonTwo.ActualWidth)
    {
        Pop2.IsOpen = false;
    }
}