为什么 ContextMenuOpening 的 Source 对 Canvas 和 UserControl 的行为不同?
Why does Source for ContextMenuOpening behave differently for Canvas and UserControl?
我有一个简单的window:
<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 itself is a FrameworkElement derived class, but this event will not be raised from the context menu being opened as a source. The event is raised from the element that "owns" the context menu as a property...
如果我没理解错的话,Source
在第一种情况下应该是Canvas
,但实际上不是。
RoutedEventArgs.OriginalSource 属性:
的 MSDN 文档中很好地介绍了此行为
Source adjustment by various elements and content models varies from class to class. Each class that adjusts event sources attempts to anticipate which source is the most useful to report for most input scenarios and the scenarios for which the class is intended, and then sets that source as the Source. If this source is not the one that has relevance to your handling of the event, try checking OriginalSource instead to see if it reports a different source that is more suitable.
这正是 UserControl class 所做的,它在其 AdjustBranchSource() 方法中修补了 Source 属性。
因此,正如引用文本所暗示的,您可能正在寻找 OriginalSource 属性 以使代码的行为相似,在这两种情况下您都将获得对 Rectangle 的引用。
我有一个简单的window:
<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 itself is a FrameworkElement derived class, but this event will not be raised from the context menu being opened as a source. The event is raised from the element that "owns" the context menu as a property...
如果我没理解错的话,Source
在第一种情况下应该是Canvas
,但实际上不是。
RoutedEventArgs.OriginalSource 属性:
的 MSDN 文档中很好地介绍了此行为Source adjustment by various elements and content models varies from class to class. Each class that adjusts event sources attempts to anticipate which source is the most useful to report for most input scenarios and the scenarios for which the class is intended, and then sets that source as the Source. If this source is not the one that has relevance to your handling of the event, try checking OriginalSource instead to see if it reports a different source that is more suitable.
这正是 UserControl class 所做的,它在其 AdjustBranchSource() 方法中修补了 Source 属性。
因此,正如引用文本所暗示的,您可能正在寻找 OriginalSource 属性 以使代码的行为相似,在这两种情况下您都将获得对 Rectangle 的引用。