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?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top