隐形打开的弹出窗口 [英] Invisible opened popup
问题描述
第二天与这个问题作斗争.
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
并不是即时的.例如,当我尝试在Popup
的MouseMove
事件中将其设置为false
时,在此期间,我得到了Button
的MouseEnter
和MouseMove
事件被触发
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 窗口中将有2 M,而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:
- 在弹出窗口关闭后(bash异步)将
IsOpen
显式设置为false
- #1 +在弹出
IsOpen == true
期间禁用按钮
- Explicitly set
IsOpen
tofalse
, after the popup closed (bash async) - #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屋!