Non chiudere ContextMenuStrip sulla selezione di alcune voci
-
22-08-2019 - |
Domanda
E 'possibile lasciare un ContextMenuStrip aperta dopo una selezione / controllo di alcune voci?
Ho intenzione di utilizzare un semplice ContextMenuStrip per impostare un filtro (in questo modo ho potuto utilizzare lo stesso filtro sia in un menu o come opzione destro del mouse).
Il menu elenca una serie di elementi, e vorrei che l'utente sia in grado di effettuare una selezione degli elementi utilizzando le funzionalità di base Check. Una volta che la selezione è fatta l'utente può fare clic su un'opzione di filtro Attivare o può fare clic all'esterno del menu per attivare o annullare il filtro.
In una selezione / click caso il menu si chiude normalmente. E 'possibile mantenere il menu aperto su un evento click?
Soluzione
Per evitare che il menu contestuale di chiudere quando un elemento viene cliccato, effettuare le seguenti operazioni.
Su evento MouseDown di ContextMenuItems flag impostato su false quindi impostare di nuovo al vero in caso di menu contestuale di chiusura.
Esempio:
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
Altri suggerimenti
Nel caso in cui i programmatori futuri si chiedono come fare questo, questo è quello che ho capito. Questo non si chiuderà il menu contestuale se qualsiasi elemento viene cliccato. Creare l'evento menu contestuale chiusura strip e impostare un if per annullare l'evento close se vicino la ragione è itemclicked.
private void contextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
e.Cancel = true;
}
L'evento di chiusura
set e.Cancel = true per uscire dal menu aperto
unico problema è l'evento non ti dice ciò che è stato fatto clic, in modo da avere per tenere traccia di questo voi stessi. impostare una sorta di bandiera Click degli elementi che si desidera conservare il menu aperto. quindi in caso di chiusura controllare il flag e impostare e.Cancel modo appropriato.
Non credo che ci sia una proprietà per questo nel ContextMenuStrip.
La soluzione che usiamo nella nostra applicazione è che sull'evento cliccato del ContextMenuStrip, facciamo un po 'di elaborazione, quindi se vogliamo che il menu contestuale per rimanere aperto chiamiamo semplicemente di nuovo ContextMenuStrip.Show.
Questo funziona bene se c'è solo un livello al ContextMenuStrip. Se ci sono sotto-menu e sotto-menu secondari, allora si dovrà selezionare nuovamente i menu che erano aperte prima del click e io non sono sicuro di come ciò può essere fatto ...
OnClosing, do: e.Cancel = e.CloseReason = ToolStripDropDownCloseReason.CloseCalled; e poi, quando si decide di chiudere, chiamare Close ().
Questo è il mio metodo; è priva di sfarfallio e - credo -. un po 'più flessibile
Se si dispone di un set di ToolStripMenuItems ti piacerebbe utilizzare i tasti a levetta (opzione on / off) come, provate questo:
(La ctxWildCards
è solo la mia ContextMenuStrip
, utilizzato per selezionare i filtri in base a tipi di file - per la ricerca o FileDialogs)
Questo è in Visual Basic (ovviamente;), in modo da poter aggiungere i gestori di programmazione o l'utilizzo 'maniglie ...' clausole
. 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
Quello che ho trovato strana è che ContextMenuStrip.Closing
generato l'evento prima il ToolStripMenuItem.Click
evento. La soluzione era quella di utilizzare ContextMenuStrip.ItemClicked
evento in cui si dispone di e.ClickedItem
, e quindi verificare se si tratta di uno degli elementi che, se cliccato, non chiuderà la ContextMenuStrip
, e impostare il flag appropriato. Poi, nel e.Cancel = true;
è possibile impostare <=> se anche è impostato il flag. Non dimenticate di resettare la bandiera però.
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;
}
}
}
Il modo migliore che ho trovato per fare questo senza sfarfallio è quello di utilizzare gli eventi MouseDown e MouseLeave per ogni tasto nel menu a discesa.
Esempio:
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
Ho trovato questo utile per i miei scopi.
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
Si potrebbe utilizzare ItemClicked
per leggere il tag o qualche altra proprietà.
Volevo solo un semplice elemento che ha reso chiaro per l'utente, che voce di menu contestuale stava per effettuare.