隐形打开弹窗 [英] Invisible opened popup

查看:18
本文介绍了隐形打开弹窗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解决这个问题的第二天.

Second day fighting this issue.

要重现,创建新的 WPF 应用程序 xaml

To reproduce, create new WPF application, xaml

<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
    <Button Width="100" Height="100" MouseMove="Button_MouseMove"/>
    <Popup x:Name="popup" StaysOpen="False" AllowsTransparency="True" Placement="Center">
        <TextBlock>Some random text</TextBlock>
    </Popup>
    <CheckBox IsChecked="{Binding (Popup.IsOpen), ElementName=popup}">Popup</CheckBox>
</StackPanel>

和代码

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

鼠标悬停按钮打开弹出窗口,点击其他地方关闭.单击按钮有错误:弹出是 IsOpen == true(可以在复选框上看到或在处理程序中带有断点),而它是不可见的.

Mouseover button to open popup, click elsewhere to close. Click button to have bug: popup is IsOpen == true (can be seen on checkbox or with breakpoint in handler), while it is invisible.

WTF?

我原来的问题是,似乎设置IsOpen 不是即时的.例如,当我尝试在 PopupMouseMove 事件中将其设置为 false 时,我得到 MouseEnterButtonMouseMove 事件在此期间触发

And my original problem is, it seems, what setting IsOpen is not instant. To example, when I try to set it to false in Popup's MouseMove event, then I get MouseEnter and MouseMove events of Button fired right during that

IsOpen = true;

与设置为true相同,有2个(!)MouseMove事件发生,将此行放入事件处理程序中查看

Same with setting it to true, there are 2 (!) MouseMove events occurs, put this line into event handler to see it

System.Diagnostics.Trace.WriteLine("M");

VS的Output窗口会有2M,而Popup(当StayOpen=false时)假设捕捉鼠标事件和会,但不会立即.

There will be 2 M in the Output window of VS, while Popup (when StayOpen=false) suppose to capture mouse events and it does, but not immediately.

谁能解释一下这是怎么回事?我不希望在期间(或不久之后?如何检查这是否是真的?)设置IsOpen 发生任何事件.已经尝试了很多东西:Dispatcher.InvokeAsync、变量、定时器等

Can someone explain me what it going on? I want no events to occurs during (or shortly after? how to check if this is true?) setting IsOpen. Tried already dozens of things: Dispatcher.InvokeAsync, variables, timers, etc.

推荐答案

我认为你对异步假设是正确的.在焦点丢失期间,IsOpen 的值设置为false,但按钮的MouseMove 触发将其重新设置为打开状态.里面的一些奇怪的魔法然后破坏了代码.

I think you are right with the asynchronous assumption. During the focus loss, the value of IsOpen is set to false, but the MouseMove of the button triggers to set it open again. Some strange magic inside then breaks the code.

根据您的需要,我找到了 2 个可能的解决方案:

2 possible solutions I found, depending on your needs:

  1. 在弹出窗口关闭后将 IsOpen 显式设置为 false(bash 异步)
  2. #1 + 在弹出期间禁用按钮 IsOpen == true
  1. Explicitly set IsOpen to false, after the popup closed (bash async)
  2. #1 + Disable the button during the popup IsOpen == true

第一种方法将在单击按钮期间隐藏弹出窗口.第二种方法会伴随着轻微的闪烁 - 当快速单击按钮时 - 但它会保持弹出窗口打开:

The first approach will hide the popup during clicking on the button. The second approach will come along with a slight flickering - when rapidly clicking the button - but it keeps the popup open:

对于第一种方法,使用以下事件处理程序(您可能不会先检查属性):

For the first approach, use the following event handlers (you might not check the property first):

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

private void Popup_OnClosed(object sender, EventArgs e)
{
    if (popup.IsOpen)
        popup.IsOpen = false;
}

对于第二种方法,使用 BoolInvertConverter 并将其以一种方式绑定到弹出窗口:

For the second approach, use a BoolInvertConverter and bind it one way to the popup:

IsEnabled="{Binding (Popup.IsOpen), ElementName=popup, Converter={StaticResource BoolInvertConverter}, Mode=OneWay}"

这篇关于隐形打开弹窗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆