Não feche ContextMenuStrip na seleção de alguns itens
-
22-08-2019 - |
Pergunta
É possível deixar um ContextMenuStrip aberto após uma seleção / verificação de certos itens?
Estou pensando em usar um simples ContextMenuStrip para definir um filtro (desta forma eu poderia usar o mesmo filtro ou em um menu ou como uma opção de clique com o botão direito).
O menu lista uma série de itens, e eu gostaria que o usuário seja capaz de fazer uma seleção dos itens utilizando a funcionalidade básica Check. Uma vez que a seleção é feita, o usuário pode clicar em uma opção de filtro Ativar ou pode clicar fora do menu para quer activar ou cancelar o filtro.
Em uma seleção / clique evento no menu normalmente fecha. É possível manter o aberto menu de um evento de clique?
Solução
Para evitar que o contextmenu de fechar quando um item é clicado, faça o seguinte.
No evento mousedown de ContextMenuItems definir o sinalizador como false, em seguida, configurá-lo de volta à verdade no evento de encerramento do contextmenu.
Exemplo:
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
Outras dicas
No caso de futuros programadores estão se perguntando como fazer isso, isso é o que eu descobri. Isso não vai fechar o menu de contexto, se algum item é clicado. Criar o evento menu de contexto fechamento de strip e configurar um if para cancelar o evento perto se perto razão é itemclicked.
private void contextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
e.Cancel = true;
}
o evento de encerramento
set e.Cancel = true para sair do menu aberto
único problema é o evento não lhe diz o que foi clicado, então você tem que manter o controle de isso sozinho. definir algum tipo de bandeira no evento Click dos itens que você deseja manter o menu aberto. em seguida, em caso de encerramento verificar a bandeira e definir e.Cancel de forma adequada.
Eu não acho que há uma propriedade para isso no ContextMenuStrip.
A solução alternativa que usamos em nossa aplicação é que no evento clicado do ContextMenuStrip, nós fazer algum processamento e, em seguida, se queremos que o menu de contexto para permanecer aberto apenas chamamos ContextMenuStrip.Show novamente.
Isto irá funcionar bem se houver apenas um nível para o ContextMenuStrip. Se houver sub-menus e sub-sub-menus, então você teria que re-selecionar os menus que estavam abertos antes do clique e eu não sei como isso pode ser feito ...
OnClosing, fazer: e.Cancel = e.CloseReason = ToolStripDropDownCloseReason.CloseCalled; e então quando você decidir fechar, chamada Close ().
Este é o meu método; -lo de e sem cintilação - penso eu -. um pouco mais flexível
Se você tem um conjunto de ToolStripMenuItems que você gostaria de usar como botões de alternância (opção on / off), tente o seguinte:
(A ctxWildCards
é apenas a minha ContextMenuStrip
, usado para selecionar filtros com base em tipos de arquivos - para a pesquisa ou FileDialogs)
Esta é em Visual Basic (obviamente;)., Para que possa adicionar manipuladores de programação ou usando 'Handles ...' cláusulas
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
O que eu achei estranho é que evento é acionado ContextMenuStrip.Closing
antes caso ToolStripMenuItem.Click
. A solução foi usar evento ContextMenuStrip.ItemClicked
onde você tem e.ClickedItem
, e em seguida, verifique se é um dos itens que, quando clicado, não vai fechar o ContextMenuStrip
, e definir o sinalizador apropriado. Então, em ContextMenuStrip.Closing
você pode definir e.Cancel = true;
se o sinalizador também está definido. Não se esqueça de redefinir o sinalizador embora.
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;
}
}
}
A melhor maneira que eu encontrei para fazer isso sem cintilação é usar os eventos MouseDown e MouseLeave para cada botão no menu suspenso.
Exemplo:
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
Eu encontrei este útil para os meus propósitos.
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
Você pode usar ItemClicked
para ler a etiqueta ou alguma outra propriedade.
Eu só queria um simples item que deixou claro para o usuário qual item do menu de contexto ia efeito.