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

时间:2012-03-15 15:13:34

标签: wpf

我在画布中添加了带有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.Source as 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并得到类似的问题。

1 个答案:

答案 0 :(得分:1)

执行此操作的一种非常快速和肮脏的方法是将您的行添加到菜单项的标记属性并在PreviewMouseDown处理程序中检索它

创建上下文菜单时:

newMenuItem1.Tag = g;

在你的经纪人:

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

执行此操作的快速和脏的方法是在您的线路上使用ContextMenuOpening事件,因为它应该与发送方等同于控件本身一起发送。然后,您可以在某处存储对该行的引用,并在菜单项单击事件中再次检索它。当你有多行(我猜是你想要的)和一个上下文菜单(而不是像你现在那样生成一堆相同菜单的副本)时,这会更好。