Update on 5/10/2018. orhtej2 suggested that my question might be a dup of Determine what control the ContextMenuStrip was used on. It is almost a dup, but my scenario has one significant difference. See my modified question and my answer for details.
See my code below. My goal is more cleanly determine which TreeNode is right-clicked after one of its ContextMenuItems is left clicked.
As it is now, when I right-click one of the two child nodes, the if
statement in the TreeView1_NodeMouseClick
loads the clicked TreeNode
into the global treeViewClickedNode
TreeNode
object. Then, when I left click one of the two contextMenuStripChildNode
ToolStripMenuItem
, the DocumentActionToolStripMenuItem_CheckStateChanged
method is fired. I can then examine the check state. If its checked, I can then do something to the treeViewClickedNode
TreeNode
.
My question: Is there a cleaner way to determine which TreeNode is right clicked after one of its ContextMenuStrip items is left clicked, i.e., is there a way to do away with the global variable treeViewClickedNode
?
Note: The only thing I did in the designer was to place treeview1
on Form1
, dock it to Form1
and set 'treeview1' NodeMouseClick
to TreeView1_NodeMouseClick
using System;
using System.Windows.Forms;
namespace WindowsFormsApp_Scratch
{
public partial class Form1 : Form
{
TreeNode treeViewClickedNode;
ContextMenu mnu = new ContextMenu();
public Form1()
{
InitializeComponent();
// Create the root node.
TreeNode treeNodeRoot = new TreeNode("Documents");
// Add the root node to the TreeView.
treeView1.Nodes.Add(treeNodeRoot);
//Create and add child 2 nodes each with a two item ContextMenuStrip.
string[] childNodeLabels = { "document1.docx", "document2.docx"};
string[] contextItemLabels = { "Action A", "Action B" };
foreach (String childNodeLabel in childNodeLabels)
{
TreeNode treeNode = treeNodeRoot.Nodes.Add(childNodeLabel);
// Create a ContextMenuStrip for this child node.
ContextMenuStrip contextMenuStripChildNode = new ContextMenuStrip
{
ShowCheckMargin = true,
ShowImageMargin = false
};
foreach (String contextItemLabel in contextItemLabels)
{
//Create a menu item.
ToolStripMenuItem action = new ToolStripMenuItem(contextItemLabel, null, DocumentActionToolStripMenuItem_CheckStateChanged)
{
CheckOnClick = true
};
contextMenuStripChildNode.Items.Add(action);
}
treeNode.ContextMenuStrip = contextMenuStripChildNode;
}
private void TreeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeView t = (TreeView)sender;
//Force the node that was right-clicked to be selected
t.SelectedNode = t.GetNodeAt(e.X, e.Y);
if (e.Button == MouseButtons.Right)
{
treeViewClickedNode = e.Node;
}
}
private void DocumentActionToolStripMenuItem_CheckStateChanged(object sender, EventArgs e)
{
ToolStripMenuItem toolStripMenuItem = (ToolStripMenuItem)sender;
if (toolStripMenuItem.CheckState == CheckState.Checked)
{
//Do something with treeViewClickedNode object
}
}
}
}
The For a ContextMenuStrip
portion of the answer for S.O. question Determine what control the ContextMenuStrip was used on almost answers my question.
In my case, however, I want to process the ContextMenuStrip
item right-click and access the ContextMenuStrip
item's CheckState
when the CheckState
changes, so my code uses a ContextMenuStrip
item _CheckStateChanged
event method instead of a ContextMenuStrip
item _Click
event method. As such, I need to cast the sender to a ToolStripMenuItem
instead of a ToolStripItem
. Other than that, I use the For a ContextMenuStrip
portion of the answer from the S.O. question Determine what control the ContextMenuStrip was used on in my DocumentActionToolStripMenuItem_CheckStateChanged
event method :
private void DocumentActionToolStripMenuItem_CheckStateChanged(object sender, EventArgs e)
{
Control treeNodeControl;
ToolStripMenuItem toolStripMenuItem = (ToolStripMenuItem)sender;
// if the ToolStripMenuItem item is owned by a ContextMenuStrip ...
if (toolStripMenuItem.Owner is ContextMenuStrip contextMenuStrip)
{
// Get the TreeNode that is displaying this context menu
treeNodeControl = contextMenuStrip.SourceControl;
if (toolStripMenuItem.CheckState == CheckState.Checked)
{
//Do something with treeNodeControl.SelectedNode treeView node
}
}
}