WPF中Border控件MouseEnter与MouseLeave事件异常行为问题
鼠标悬停在Border控件上时,MouseEnter和MouseLeave事件会同时触发;离开Border控件时,这两个事件又会再次触发。而StackPanel控件的事件表现符合预期,请问该异常现象的原因是什么?
XAML代码
<StackPanel Orientation="Vertical"> <Border Name="myBorder" BorderBrush="Black" BorderThickness="2" Width="100" Height="100" MouseEnter="MyBorder_OnMouseEnter" MouseLeave="MyBorder_OnMouseLeave"> </Border> <StackPanel Width="150" Height="150" Background="Red" MouseEnter="StackPanel_OnMouseEnter" MouseLeave="StackPanel_OnMouseLeave"/> </StackPanel>
C#代码
private void MyBorder_OnMouseEnter(object sender, MouseEventArgs e) { Debug.WriteLine("MyBorder_OnMouseEnter"); } private void MyBorder_OnMouseLeave(object sender, MouseEventArgs e) { Debug.WriteLine("MyBorder_OnMouseLeave"); } private void StackPanel_OnMouseEnter(object sender, MouseEventArgs e) { Debug.WriteLine("UIElement_OnMouseEnter"); } private void StackPanel_OnMouseLeave(object sender, MouseEventArgs e) { Debug.WriteLine("UIElement_OnMouseLeave"); }
异常原因
问题核心在于Border未设置背景(Background)属性。
WPF的鼠标事件依赖控件的“命中测试”区域:只有能被命中测试的区域,才会正确响应鼠标进入/离开事件。Border默认的Background是null,此时只有它的边框部分属于可命中测试区域,内部的空白区域不算。
当鼠标移向Border时,先碰到边框触发MouseEnter;但鼠标继续移动到Border内部空白区域时,因为这部分无法被命中测试,WPF会判定鼠标已经离开Border的有效区域,立刻触发MouseLeave——这就导致刚悬停上去就同时触发了两个事件。
当鼠标离开Border时,先从内部空白区域移回边框,此时WPF认为鼠标重新进入了可命中测试区域,触发MouseEnter;接着鼠标离开边框,又触发MouseLeave——所以离开时也会同时触发两个事件。
而StackPanel设置了Background="Red",整个控件区域都属于可命中测试范围,所以鼠标进入后只要停在区域内就不会触发MouseLeave,离开时只触发一次MouseLeave,表现符合预期。
解决方法很简单:给Border设置一个Background,哪怕是透明的Background="Transparent",这样整个Border区域都会被纳入命中测试,鼠标事件就能正常工作了。
内容的提问来源于stack exchange,提问作者esege

