Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Is it possible to leave a ContextMenuStrip open after a selection/check of certain items?

I plan on using a simple ContextMenuStrip to set a filter (this way i could use the same filter either in a menu or as a right-click option).

The menu lists a number of items, and i would like the user to be able to make a selection of the items using the basic Check functionality. Once the selection is done the user can click an Activate filter option or can click outside the menu to either activate or cancel the filter.

On a selection/click event the menu normally closes. Is it possible to keep the menu open on a click event?

In case future programers are wondering how to do this, this is what I figured out. This will not close the context menu if any item is clicked. Create the context menu strip closing event and setup an if statement to cancel the close event if close reason is itemclicked.

private void contextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
    if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
        e.Cancel = true;
                If I understand the question correctly, this doesn't really answer it fully, in that they only want to leave the context menu open for some of the items. E.g. the context menu items are: Option A, Option B, Option C and Accept; the context menu should be left open if one of the options is clicked (the option will then be checked), however if Accept is clicked the context menu should be closed.
– jonvw
                Aug 5, 2016 at 18:37
                This does not correctly solve the problem. See this answer: stackoverflow.com/a/38659888 for a complete solution.
– Ryan_S
                Sep 3, 2020 at 21:43
                This seems to work more elegant than the show solution. I set the e.Cancel to true in the Closing event of the ContextMenu based on a flag as suggested and set the flag on the individual clicked items. However since the Cancel event is only set during the closing event it lags one step behind. Is there a way to set the Cancel flag in for the closing event in the item click events?
– barry
                May 25, 2009 at 6:16

To prevent the contextmenu from closing when an item is clicked, do the following.

On mousedown event of ContextMenuItems set flag to false then set it back to true at the closing event of the contextmenu.

Example:

Private blnClose As Boolean = True
Private Sub MoveUpToolStripMenuItem_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MoveUpToolStripMenuItem.MouseDown
     blnClose = False
End Sub
Private Sub ContextMenuStrip1_Closing(ByVal sender As Object, ByVal e As System.Windows.Forms.ToolStripDropDownClosingEventArgs) Handles ContextMenuStrip1.Closing
     e.Cancel = Not blnClose
     blnClose = True
End Sub
                -1 You selected the answer which isn't in the language you're coding in, and one that suggests to use a global variable???  There are way more related answers here.
– Lee Louviere
                Apr 13, 2011 at 21:50
                This does not correctly solve the problem. See this answer: stackoverflow.com/a/38659888 for a complete solution.
– Ryan_S
                Sep 3, 2020 at 21:45

What i found strange is that ContextMenuStrip.Closing event fires before the ToolStripMenuItem.Click event. The solution was to use ContextMenuStrip.ItemClicked event where you have e.ClickedItem, and then check if it's one of the items that, when clicked, won't close the ContextMenuStrip, and set the appropriate flag. Then in ContextMenuStrip.Closing you can set e.Cancel = true; if the flag is also set. Don't forget to reset the flag though.

bool isRunAtStartupClicked;
private void ContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    if (e.ClickedItem == trayIcon.ContextMenuStrip.Items["miRunAtStartup"])
        isRunAtStartupClicked = true;
private void ContextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
    if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
        if (isRunAtStartupClicked)
            isRunAtStartupClicked = false;
            e.Cancel = true;

I don't think there is a property for this in the ContextMenuStrip.

The workaround we use in our application is that on the clicked event of the ContextMenuStrip, we do some processing, then if we want the context menu to stay open we simply call ContextMenuStrip.Show again.

This will work well if there is only one level to the ContextMenuStrip. If there are sub-menus and sub-sub-menus, then you would have to re-select the menus that were open before the click and I'm not sure how that can be done...

Thanks! I checked and this works perfect for one level menus. I will leave the question open for a while longer to see if there is another option. – barry May 16, 2009 at 8:39

This is my method; it's flicker-free and - I think - a bit more flexible.

If you have a set of ToolStripMenuItems you'd like to use as toggle buttons (option on/off), try this:

(The ctxWildCards is just my ContextMenuStrip, used to select filters based on file types - for search or FileDialogs)

This is in Visual Basic (obviously! ;), so you can add Handlers programmatically or using 'Handles...' clauses.

  Private Sub OnOffToolStripMenuItem_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) 
    Dim t = TryCast(sender, ToolStripMenuItem)
    If Not t Is Nothing Then
        'Since you may have more On/off-Items, check to see if the Owner is the ContextMenuStrip 
        If t.Owner Is ctxWildCards Then
           ' The ContextMenuStrip will stay open on Right-click, i.e. the user can check and close by clicking 'normally'
            ctxWildCards.AutoClose = (e.Button = Windows.Forms.MouseButtons.Left)
        End If
        'Just me using a custom image for checked items.
        t.Checked = Not t.Checked
        t.Image = If(t.Checked, rdoImage, Nothing)
    End If
  End Sub
 ' On leaving ToolStripMenuItems of the ContextMenuStrip, allow it to AutoClose
  Private Sub OnOffToolStripMenuItem_MouseLeave(sender As System.Object, e As System.EventArgs)
  ctxWildCards.AutoClose = True
End Sub

The best way I found to do this without flickering is to use the MouseDown and MouseLeave events for every button in the DropDown menu.

Example:

Private Sub ToolStripMenuItem2_Mousedown(sender As Object, e As EventArgs) Handles ToolStripMenuItem2.MouseDown
        ΥπηρεσίεςToolStripMenuItem.DropDown.AutoClose = False
End Sub
Private Sub ToolStripMenuItem2_MouseLeave(sender As Object, e As EventArgs) Handles ToolStripMenuItem2.MouseLeave
        ΥπηρεσίεςToolStripMenuItem.DropDown.AutoClose = True
End Sub

I found this useful for my purposes.

Private Sub CM_Closing(sender As Object, e As ToolStripDropDownClosingEventArgs) Handles CM.Closing
    If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
        Dim ItemClicked As String = CM.GetItemAt(New Point(Cursor.Position.X - CM.Left, Cursor.Position.Y - CM.Top)).Name
        If ItemClicked = "CMHeader" Then
            e.Cancel = True
        End If
    End If
End Sub

You could use ItemClicked to read the tag or some other property.

I just wanted a simple item that made clear to the user which item the context menu was going to effect.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.