菜单单击事件对象参数引用菜单,而不是基础对象



我在画布中添加了一个带有C#代码的Line,以及一个上下文菜单和附加的事件。我想使用上下文菜单选项旋转Line,而不是上下文菜单中的菜单文本:

newMenuItem1.PreviewMouseDown += new  MouseButtonEventHandler((sx, ex) => {
            MenuItem menuItem = (MenuItem)sx;
            string theHeader = menuItem.Header.ToString();
            if (theHeader.Contains("90")) {
                Line ow = ex.Source as Line;
                rt = new RotateTransform(90, 25, 50);
                ow.RenderTransform = rt;
            }
        });

此代码生成一个null reference exception。如果我替换:

UIElement ow=ex.来源为UIElement;

实际菜单文本将旋转!

编辑:这是更多的代码,我现在也在尝试originalsource

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Line g = new Line();
        g.Stroke = System.Windows.Media.Brushes.LawnGreen;
        g.X1 = 0; g.X2 = 100;g.Y1 = 0;g.Y2 = 0;
        g.HorizontalAlignment = HorizontalAlignment.Left;
        g.VerticalAlignment = VerticalAlignment.Center;
        g.StrokeThickness = 6;
        ContextMenu k = new ContextMenu();
        g.ContextMenu = k;
        MenuItem newMenuItem1 = new MenuItem();
        MenuItem newMenuItem2 = new MenuItem();
        MenuItem newMenuItem3 = new MenuItem();
        newMenuItem1.Header = "Rotate 90";
        newMenuItem2.Header = "Rotate 180";
        newMenuItem3.Header = "Rotate 270";
        newMenuItem1.PreviewMouseDown += new MouseButtonEventHandler((sx, ex) => {
            MenuItem menuItem = (MenuItem)sx;
            string theHeader = menuItem.Header.ToString();
            if (theHeader.Contains("90")) {
                Line ow = (Line)ex.OriginalSource;
                rt = new RotateTransform(90, 25, 50);
                ow.RenderTransform = rt;
            }
        });
        g.ContextMenu.Items.Add(newMenuItem1);
        g.ContextMenu.Items.Add(newMenuItem2);
        g.ContextMenu.Items.Add(newMenuItem3);
        Canvas.SetTop(g, 18);
        Canvas.SetLeft(g, 18);
        MyCanvas.Children.Add(g);
        ///////

我也试过:

 private static T FindAncestor<T>(DependencyObject current)
    where T : DependencyObject
    {
        do
        {
            if (current is T)
            {
                return (T)current;
            }
            current = VisualTreeHelper.GetParent(current);
        }
        while (current != null);
        return null;
    }

但它不起作用。我的下一个计划是从画布上获取坐标,并尝试确定那里有什么控件。不过,如果对象被转换,这将变得棘手,因为我相信UI会在原始位置看到它。我也尝试过其他控件,比如TextBox,但也遇到了类似的问题。

一个真正快速而肮脏的方法是将行添加到菜单项的标记属性中,并在PreviewMouseDown处理程序中检索它

创建上下文菜单时:

newMenuItem1.Tag = g;

内部处理程序:

Line ow = ((FrameworkElement)ex.Source).Tag as Line;

要做到这一点,不那么快速和肮脏的方法是在您的行中使用ContextMenuOpening事件,因为发送该事件的发送方应等于控件本身。然后,您可以将对该行的引用存储在某个位置,并在菜单项单击事件中再次检索该行。当你有多行(我想这就是你想要的)和只有一个上下文菜单(而不是像现在这样生成同一菜单的一堆副本)时,效果会更好。

最新更新