Question

Similar to this question: get contextmenustrip from toolstripmenuitem

Except that now I need to find the object whose context menu was opened when the ToolStripMenuItem was clicked.

SourceControl, Parent, Owner, and GetParentControl() all return null.

Initially I had a TreeView, and it's ContextMenuStrip property was set.

Here's my preliminary code:

        ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
        ToolStripMenuItem tsmip = (ToolStripMenuItem)tsmi.OwnerItem;
        ContextMenuStrip cms = (ContextMenuStrip)tsmip.GetCurrentParent();
        TreeView tv = (TreeView)cms.SourceControl; 
        // returns null, but not in the cms_openHandler
        tv.Nodes.Add(new TreeNode("event fired."));

Am I getting the ContextMenuStrip improperly? Why is it that the SourceControl property of the cms works in the OpenHandler, but not from the ToolStripMenuItem eventhandler?

Form1.Designer.cs:

namespace TestWFA
{
partial class Form1
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.components = new System.ComponentModel.Container();
        this.treeView1 = new System.Windows.Forms.TreeView();
        this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
        this.expandToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        this.childrenToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        this.allDescendantsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        this.collapseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        this.childrenToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
        this.parentToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
        this.childrenToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
        this.allDescendantsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
        this.contextMenuStrip1.SuspendLayout();
        this.SuspendLayout();
        // 
        // treeView1
        // 
        this.treeView1.ContextMenuStrip = this.contextMenuStrip1;
        this.treeView1.Location = new System.Drawing.Point(64, 75);
        this.treeView1.Name = "treeView1";
        this.treeView1.Size = new System.Drawing.Size(262, 247);
        this.treeView1.TabIndex = 0;
        // 
        // contextMenuStrip1
        // 
        this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
        this.expandToolStripMenuItem,
        this.collapseToolStripMenuItem});
        this.contextMenuStrip1.Name = "contextMenuStrip1";
        this.contextMenuStrip1.Size = new System.Drawing.Size(153, 70);
        this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening);
        // 
        // expandToolStripMenuItem
        // 
        this.expandToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
        this.childrenToolStripMenuItem,
        this.allDescendantsToolStripMenuItem});
        this.expandToolStripMenuItem.Name = "expandToolStripMenuItem";
        this.expandToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
        this.expandToolStripMenuItem.Text = "Expand";
        // 
        // childrenToolStripMenuItem
        // 
        this.childrenToolStripMenuItem.Name = "childrenToolStripMenuItem";
        this.childrenToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
        this.childrenToolStripMenuItem.Text = "Children";
        this.childrenToolStripMenuItem.Click += new System.EventHandler(this.childrenToolStripMenuItem_Click);
        // 
        // allDescendantsToolStripMenuItem
        // 
        this.allDescendantsToolStripMenuItem.Name = "allDescendantsToolStripMenuItem";
        this.allDescendantsToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
        this.allDescendantsToolStripMenuItem.Text = "All Descendants";
        this.allDescendantsToolStripMenuItem.Click += new System.EventHandler(this.allDescendantsToolStripMenuItem_Click);
        // 
        // collapseToolStripMenuItem
        // 
        this.collapseToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
        this.childrenToolStripMenuItem1,
        this.parentToolStripMenuItem,
        this.childrenToolStripMenuItem2,
        this.allDescendantsToolStripMenuItem1});
        this.collapseToolStripMenuItem.Name = "collapseToolStripMenuItem";
        this.collapseToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
        this.collapseToolStripMenuItem.Text = "Collapse";
        // 
        // childrenToolStripMenuItem1
        // 
        this.childrenToolStripMenuItem1.Name = "childrenToolStripMenuItem1";
        this.childrenToolStripMenuItem1.Size = new System.Drawing.Size(161, 22);
        this.childrenToolStripMenuItem1.Text = "All Ancestors";
        this.childrenToolStripMenuItem1.Click += new System.EventHandler(this.childrenToolStripMenuItem1_Click);
        // 
        // parentToolStripMenuItem
        // 
        this.parentToolStripMenuItem.Name = "parentToolStripMenuItem";
        this.parentToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
        this.parentToolStripMenuItem.Text = "Parent";
        this.parentToolStripMenuItem.Click += new System.EventHandler(this.parentToolStripMenuItem_Click);
        // 
        // childrenToolStripMenuItem2
        // 
        this.childrenToolStripMenuItem2.Name = "childrenToolStripMenuItem2";
        this.childrenToolStripMenuItem2.Size = new System.Drawing.Size(161, 22);
        this.childrenToolStripMenuItem2.Text = "Children";
        this.childrenToolStripMenuItem2.Click += new System.EventHandler(this.childrenToolStripMenuItem2_Click);
        // 
        // allDescendantsToolStripMenuItem1
        // 
        this.allDescendantsToolStripMenuItem1.Name = "allDescendantsToolStripMenuItem1";
        this.allDescendantsToolStripMenuItem1.Size = new System.Drawing.Size(161, 22);
        this.allDescendantsToolStripMenuItem1.Text = "All Descendants";
        this.allDescendantsToolStripMenuItem1.Click += new System.EventHandler(this.allDescendantsToolStripMenuItem1_Click);
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(406, 365);
        this.Controls.Add(this.treeView1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.contextMenuStrip1.ResumeLayout(false);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.TreeView treeView1;
    private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
    private System.Windows.Forms.ToolStripMenuItem expandToolStripMenuItem;
    private System.Windows.Forms.ToolStripMenuItem childrenToolStripMenuItem;
    private System.Windows.Forms.ToolStripMenuItem allDescendantsToolStripMenuItem;
    private System.Windows.Forms.ToolStripMenuItem collapseToolStripMenuItem;
    private System.Windows.Forms.ToolStripMenuItem childrenToolStripMenuItem1;
    private System.Windows.Forms.ToolStripMenuItem parentToolStripMenuItem;
    private System.Windows.Forms.ToolStripMenuItem childrenToolStripMenuItem2;
    private System.Windows.Forms.ToolStripMenuItem allDescendantsToolStripMenuItem1;
}
}

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestWFA
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        treeView1.Nodes.Add(new TreeNode("root"));
    }

    private void childrenToolStripMenuItem1_Click(object sender, EventArgs e)
    {
        TreeView tv = GetSourceControl(sender) as TreeView;

        if (tv != null)
        {
            tv.Nodes.Add("Tree event catched!");
        }

        /*ToolStripMenuItem tsmi = (ToolStripMenuItem)sender;
        ToolStripMenuItem tsmip = (ToolStripMenuItem)tsmi.OwnerItem;


        ContextMenuStrip cms = (ContextMenuStrip)tsmip.GetCurrentParent();
        ToolStrip ts = tsmip.GetCurrentParent();

        IContainer c = cms.Container;
        TreeView tv = (TreeView)c;
        tv.Nodes.Add(new TreeNode("event fired."));*/
    }

    private object GetSourceControl(object Sender)
    {
        if (Sender as ContextMenuStrip != null)
        {
            return ContextMenuStrip.SourceControl;
        }

        var item = Sender as ToolStripItem;

        // move to root item
        while (item.OwnerItem != null)
        {
            item = item.OwnerItem;
        }

        // we have root item now, so lets take ContextMenuStrip object
        var menuObject = item.Owner as ContextMenuStrip;

        if (menuObject != null)
        {
            return menuObject.SourceControl;
        }

        return null;

    }

    private void parentToolStripMenuItem_Click(object sender, EventArgs e)
    {

    }

    private void childrenToolStripMenuItem2_Click(object sender, EventArgs e)
    {

    }

    private void allDescendantsToolStripMenuItem1_Click(object sender, EventArgs e)
    {

    }

    private void childrenToolStripMenuItem_Click(object sender, EventArgs e)
    {

    }

    private void allDescendantsToolStripMenuItem_Click(object sender, EventArgs e)
    {
    }

    private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
    {
        try
        {
            ContextMenuStrip cms = (ContextMenuStrip)sender;

        }
        catch
        {
        }
        try
        {
            TreeView tv = (TreeView)sender;
        }
        catch
        {
        }
    }

}
}

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace TestWFA
{
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}
}

Unfortunately I don't know of any way to upload the files. I tried uploading them as imgs, that didn't work.

Was it helpful?

Solution

Suppose you have ContextMenuStrip setted to TreeView. You can easily get control for which menu was triggered from Opened handler for your ContextMenuStrip:

private void contextMenuStrip1_Opened(object sender, EventArgs e)
{
  TreeView tv = (sender as ContextMenuStrip).SourceControl as TreeView;
  tv.Nodes.Add("Tree event catched!");
}

This code would also work if ContextMenuStrip was set to treeView's item.

PS: In real app you shouldn't use construction like (sender as ContextMenuStrip).SourceControl as TreeView; because of possibility of null pointer. You should check for null after each cast instead.

[EDIT]
OK, now I understand your aim.
When you handle menu item sender object points to item triggered event. And to find out the control for which context menu was popped up you should do three things:

  1. Find root item. Its likely, that clicked item is subitem for another item or deeper.
  2. From root item you should find out ContextMenuStrip object
  3. It's easy to find out interesting control from ContextMenuStrip's SourceControl property

I wrote simple method to do all that job:

/// <summary>
/// Gets controls for context menu
/// </summary>
/// <param name="Sender">Sender object from menu event handler</param>
/// <returns></returns>
private object GetSourceControl(Object Sender)
{
  // ContextMenuStrip sended?
  if (Sender as ContextMenuStrip != null)
  {
    ContextMenuStrip cms = Sender as ContextMenuStrip;
    return cms.SourceControl;
  }

  var item = Sender as ToolStripItem;

  // move to root item
  while (item.OwnerItem != null)
  {
    item = item.OwnerItem;
  }

  // we have root item now, so lets take ContextMenuStrip object
  var menuObject = item.Owner as ContextMenuStrip;

  if (menuObject != null)
  {
    return menuObject.SourceControl;
  }

  return null;
}

You can simply use it. For example we have menu item click event handler:

private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
  TreeView tv = GetSourceControl(sender) as TreeView;

  if (tv != null)
  {
    tv.Nodes.Add("Tree event catched!");
  }
}

[EDIT2]
As turned out this problem was discused early ( SourceControl of ContextMenuStrip is Nothing in ToolStripMenuItem Click? ). SourceControl property is not null when you are click on root item, but in case you click subitem it equals null. So the solution is to store SourceControl's value somwhere to use later. I suggest to do this in Tag property. So all methods would be looks like:

private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
  contextMenuStrip1.Tag = (sender as ContextMenuStrip).SourceControl;
}
....

private object GetSourceControl(object Sender)
{
  if (Sender as ContextMenuStrip != null)
  {
    return ContextMenuStrip.SourceControl;
  }

  var item = Sender as ToolStripItem;

  // move to root item
  while (item.OwnerItem != null)
  {
    item = item.OwnerItem;
  }

  // we have root item now, so lets take ContextMenuStrip object
  var menuObject = item.Owner as ContextMenuStrip;

  if (menuObject != null)
  {
    return menuObject.Tag;
  }

  return null;
}

In the linked question there is workaround with private field, but Tag property is habitual for me

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top