获取按钮上上下文菜单的所有者

4

标题已经说明了一切。我有很多按钮,它们都有相同的上下文菜单,我想从点击事件中确定是哪个按钮被右键单击了。

这段代码不起作用,placementTarget 为空:

private void mi_Click(object sender, RoutedEventArgs e)
{
        Button contextMenuEzen = null;

        MenuItem mnu = sender as MenuItem;

        if (mnu != null)
        {
            ContextMenu ize =(ContextMenu)mnu.Parent;
            contextMenuEzen = ize.PlacementTarget as Button;
        }
}

请帮助我!


你能展示一下你的示例的完整代码吗?(按钮,上下文菜单) - Anatoliy Nikolaev
3个回答

4

对我来说,这个例子有效:

XAML

<Window.Resources>
    <!-- For all MenuItems set the handler -->
    <Style TargetType="{x:Type MenuItem}">
        <EventSetter Event="Click" Handler="MenuItem_Click" />
    </Style>

    <!-- One ContextMenu for all buttons (resource) -->
    <ContextMenu x:Key="MyContextMenu">
        <MenuItem Header="Click this" />
        <MenuItem Header="Two" />
        <MenuItem Header="Three" />
    </ContextMenu>
</Window.Resources>

<Grid>
    <Button x:Name="MyButton1" Width="100" Height="30" Content="MyButton1" ContextMenu="{StaticResource MyContextMenu}" />

    <Button x:Name="MyButton2" Margin="0,110,0,0" Width="100" Height="30" Content="MyButton2" ContextMenu="{StaticResource MyContextMenu}" />
</Grid>

代码后台

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    MenuItem mnu = sender as MenuItem;
    Button MyButton = null;

    if (mnu != null)
    {
        ContextMenu MyContextMenu = (ContextMenu)mnu.Parent;
        MyButton = MyContextMenu.PlacementTarget as Button;
    }

    MessageBox.Show(MyButton.Content.ToString());
}

1
你的回答只适用于你的例子,用户明确表示在他的场景中有“具有相同 ContextMenu 的多个按钮”,因此 ContextMenu 实例的 PlacementTarget 确实将为 null。 - abdelkarim
@abdelkarim:我不明白。在你的例子中,你是通过编程创建所有内容,并设置事件处理程序。试着在我的情况下创建一些带有“上下文菜单”的按钮,结果会相同。不要尝试在代码中创建元素,这不是WinForms的做法。 - Anatoliy Nikolaev

1
路由事件与普通事件不完全相同 - 处理程序的签名为 EventHandler(object sender, RoutedEventArgs e)。RoutedEventArgs 有一个名为 OriginalSource 的属性,表示实际被单击的 UI 元素。相比之下,sender 参数将始终是注册事件处理程序的对象。

你是说这样应该可以工作吗? private void mi_Click(object sender, RoutedEventArgs e) { Button contextMenuEzen = e.OriginalSource as Button;} - Wtf1sh
如果您将mi_click事件处理程序添加到按钮的单击事件中,那么是的,那应该可以工作。 - Andrew
问题是我想使用的不是Button.Click,而是在ContextMenu中的MenuItem.Click,位于Button上。 - Wtf1sh

0

使用ContextMenuService来获取放置目标,如下面的示例:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += (sender, args) => {

            RoutedEventHandler clickHandler = delegate(object o, RoutedEventArgs eventArgs) {
                var mi = (MenuItem) o;
                var contextMenu = (ContextMenu) mi.Parent;

                var pTarget = ContextMenuService.GetPlacementTarget(contextMenu) as Button;

                // just to make sure
                if (pTarget == null) {
                    return;
                }

                string message = "You clicked on the button " + pTarget.Content;
                MessageBox.Show(message);
            };

            // create a single instance of the ContextMenu
            var cm = new ContextMenu();
            for (int i = 0; i < 10; i++) {
                var mi = new MenuItem {Header = "Item " + i};
                mi.Click += clickHandler;
                cm.Items.Add(mi);
            }

            // create a set of buttons and assign them to the RootVisual(StackPanel)
            for (int i = 0; i < 5; i++) {
                var button = new Button {Content = "Button " + i, ContextMenu = cm};
                this.RootVisual.Children.Add(button);
            }
        };
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接