为什么 ContextMenuOpen 的源代码对于 Canvas 和 UserControl 的行为不同
本文关键字:UserControl Canvas ContextMenuOpen 源代码 为什么 | 更新日期: 2023-09-27 17:55:41
我有一个简单的窗口:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:self="clr-namespace:WpfApplication1"
Title="MainWindow" Height="435" Width="613">
<StackPanel>
<Canvas Name="canvas">
<self:Red />
</Canvas>
<UserControl Name="uc">
<self:Blue />
</UserControl>
</StackPanel>
</Window>
Red
和Blue
非常简单UserControls
:
<UserControl x:Class="WpfApplication1.Blue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Rectangle Fill="Blue" Width="100" Height="100" />
</Grid>
</UserControl>
我创建了一些上下文菜单:
public MainWindow()
{
InitializeComponent();
canvas.ContextMenu = new ContextMenu();
canvas.ContextMenuOpening += (sender, e) =>
{
System.Diagnostics.Debug.WriteLine(e.Source.GetType());
};
uc.ContextMenu = new ContextMenu();
uc.ContextMenuOpening += (sender, e) =>
{
System.Diagnostics.Debug.WriteLine(e.Source.GetType());
};
}
如果我在Canvas
上打开上下文菜单,Source
是Red
,但是如果我在UserControl
上打开它,Source
是UserControl
。
知道为什么吗?
我在MSDN上找到了这个:
ContextMenu 本身是一个 FrameworkElement 派生类,但此事件不会从作为源打开的上下文菜单中引发。该事件是从"拥有"上下文菜单作为属性的元素引发的...
如果我理解正确Source
在第一种情况下应该Canvas
,但事实并非如此。
此行为在 RoutedEventArgs.OriginalSource 属性的 MSDN 文档中得到了很好的介绍:
各种元素和内容模型的源调整因类而异。每个调整事件源的类都尝试预测哪个源最有用,用于报告大多数输入方案和该类所针对的方案,然后将该源设置为源。如果此源不是与您处理事件相关的源,请尝试改为检查 OriginalSource,看看它是否报告了更合适的其他源。
这正是UserControl类所做的,它在其AdjustBranchSource()方法中修补Source属性。
因此,正如引用的文本所暗示的那样,您可能正在寻找 OriginalSource 属性以使代码的行为类似,在这两种情况下,您都会获得对矩形的引用。