2

I have a TreeView control for which each node in it I want to share a ContextMenuStrip which has two ToolStripMenuItems ie:

this.BuildTree = new MyApp.MainForm.TreeView();
this.ItemMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.DeleteMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowLogMenuItem = new System.Windows.Forms.ToolStripMenuItem();
...
this.ItemMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.DeleteMenuItem,
this.ShowLogMenuItem});

So I show and hide these to items according to certain criteria on a right click in a MouseUp event. When both are hidden I hide the ContextMenuStrip itself. Problem is when I hide the ContextMenuStrip it seems the next time I want to show one of the menu items I have to click twice on the node. The strange thing is on the first click to reshow one or both of the the items I have the following code:

ItemMenuStrip.Visible = true;
ShowLogMenuItem.Visible = true;

The two lines above don't seem to do anything ie both remain false in the debugger view after stepping over each line.

I don't think I've got any events on these values being set at least I don't have any events attached.

What am I doing wrong?

Dominic Zukiewicz
  • 8,258
  • 8
  • 43
  • 61
user176168
  • 1,294
  • 1
  • 20
  • 30
  • 1
    Visibility is also part of the parent control. Since you are in the process of 'opening', you don't have a UI and therefore not visible. From trial and error I've found even though the get/set aren't straight assignments, it does remember what you have set it as before rendering. The `.Visible` is then used appropriately when the control is displayed. – Dominic Zukiewicz Feb 07 '13 at 15:23

2 Answers2

3

I suggest you to set:

this.BuildTree.ContextMenuStrip = this.ItemMenuStrip;

to make the menu automatically open on tree right-click.

Then subscribe ItemMenuStrip.Opening event to change the visibility of items and the contextmenu itself:

void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
    if (something)
    {
        e.Cancel = true; // don't show the menu
    }
    else
    {
        // show/hide the items...
    }
}

If you need to know the current position of the clicked point (e.g. to check if a tree node is clicked), you can use Control.MousePosition property. Note that MousePosition is a point in screen coordinates, so you need to call treeView1.PointToClient(position) to get the tree coordinates e.g. :

private void ItemMenuStrip_Opening(object sender, CancelEventArgs e)
{
    var pointClicked = this.BuildTree.PointToClient(Control.MousePosition);
    var nodeClicked = this.BuildTree.GetNodeAt(pointClicked);
    if (nodeClicked == null) 
    {
        // no tree-node is clicked --> don't show the context menu
        e.Cancel = true;
    }
    else
    {
        // nodeClicked variable is the clicked node;
        // show/hide the context menu items accordingly
    }
}
digEmAll
  • 56,430
  • 9
  • 115
  • 140
  • Sorry that didn't work either and I tried it using Available. One thing I did notice is that if I just use Available or Visible and don't hide the actual ItemMenuStrip then when I right click the node which has an empty ItemMenuStrip I see an empty ItemMenuStrip but the next click (the problem one) I don't see anything as if the draw isn't happening. – user176168 Mar 20 '12 at 11:32
  • This worked but beware of the observer effect. I had a breakpoint set and the Visible always appeared to be false in my debugging tools but it was because when the breakpoint hit in Visual Studio the whole context menu was hidden thus forcing visible to be false. – kampsj Sep 05 '13 at 19:11
0

So figured out what was going wrong I was setting Visible on this.ItemMenuStrip rather than the this.BuildTree.ContextMenuStrip.

This seems rather strange to me as I would have thought BuildTree.ContextMenuStrip was just a direct reference to the ItemMenuStrip but apparently not.

user176168
  • 1,294
  • 1
  • 20
  • 30