看不见的打开的弹出框
本文关键字:看不见 | 更新日期: 2023-09-27 18:10:45
抗争第二天
要重新创建新的WPF应用程序,请使用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;
}
鼠标悬停按钮打开弹出窗口,单击其他地方关闭。点击按钮有bug:弹出是IsOpen == true(可以在复选框上看到或在处理程序中有断点),而它是不可见的。
WTF ?
我原来的问题是,似乎,什么设置IsOpen
不是即时的。例如,当我尝试在Popup
的MouseMove
事件中将其设置为false
时,我会在
Button
的MouseEnter
和MouseMove
事件。IsOpen = true;
同样设置为true
,有2个(!)发生MouseMove
事件,将这行放入事件处理程序中查看
System.Diagnostics.Trace.WriteLine("M");
在VS的Output窗口中将有2 M,而Popup
(当StayOpen=false
)假设捕获鼠标事件并且确实如此,但不是立即。
IsOpen
。已经尝试了很多东西:Dispatcher.InvokeAsync
,变量,计时器等
我认为你的异步假设是对的。在失焦期间,IsOpen
的值被设置为false,但按钮的MouseMove
触发将其重新设置为打开。一些奇怪的魔法会打破密码。
根据你的需要,我找到了两个可能的解决方案:
- 显式设置
IsOpen
为false
,在弹出窗口关闭后(bash async) - #1 +在弹出时禁用按钮
IsOpen == true
第一种方法将在单击按钮时隐藏弹出窗口。第二种方法会伴随着轻微的闪烁——当快速点击按钮时——但它会保持弹出窗口打开:
对于第一种方法,使用以下事件处理程序(您可能不会首先检查属性):
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
并以一种方式绑定到弹出窗口:
IsEnabled="{Binding (Popup.IsOpen), ElementName=popup, Converter={StaticResource BoolInvertConverter}, Mode=OneWay}"
当您按下按钮时(即使使用空格键),MouseMove
和MouseEnter
都被调用,因此这会导致Popup
试图关闭而同时将IsOpen
设置为true的情况。简单的解决方案是将这两个事件分开。
一种可能的方法是在给定的Button
上悬停时,坚持MouseEnter
并打开Popup
一次。例如:
private Button currentPopupHolder;
private void Button_MouseEnter(object sender, MouseEventArgs e)
{
var btn = sender as Button;
if (currentPopupHolder != btn)
{
popup.IsOpen = true;
currentPopupHolder = btn;
}
}
private void Button_MouseLeave(object sender, MouseEventArgs e)
{
currentPopupHolder = null;
}
当相同的Button
产生这个事件时,Popup
不应该被打开超过一次(包括按钮被按下的时间)