Pergunta

Como posso descobrir em qual nó de uma lista em árvore o menu de contexto foi ativado?Por exemplo, clicar com o botão direito em um nó e selecionar uma opção no menu.

Não consigo usar o TreeViews' SelectedNode propriedade porque o nó foi clicado apenas com o botão direito e não selecionado.

Foi útil?

Solução

Você pode adicionar um evento de clique do mouse ao TreeView e selecionar o nó correto usando GetNodeAt dadas as coordenadas do mouse fornecidas pelo MouseEventArgs.

void treeView1MouseUp(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Right)
    {
        // Select the clicked node
        treeView1.SelectedNode = treeView1.GetNodeAt(e.X, e.Y);

        if(treeView1.SelectedNode != null)
        {
            myContextMenuStrip.Show(treeView1, e.Location);
        }
    }
}

Outras dicas

Aqui está minha solução.Coloque esta linha no evento NodeMouseClick do TreeView:

 ((TreeView)sender).SelectedNode = e.Node;

Acho que o comportamento padrão de seleção do comportamento da visualização em árvore do Windows é bastante irritante.Por exemplo, se você estiver usando o Explorer e clicar com o botão direito em um nó e clicar em Propriedades, ele destacará o nó e mostrará a caixa de diálogo de propriedades do nó em que você clicou.Mas quando você retorna da caixa de diálogo, o nó destacado é o nó previamente selecionado/destacado antes de você clicar com o botão direito.Acho que isso causa problemas de usabilidade porque fico sempre confuso sobre se agi no nó certo.

Portanto, em muitas de nossas GUIs, alteramos o nó da árvore selecionado clicando com o botão direito para que não haja confusão.Isso pode não ser o mesmo que um aplicativo iwndos padrão como o Explorer (e eu costumo modelar fortemente nosso comportamento da GUI após aplicativos de janela padrão por motivos de usabilidade). Acredito que esse caso de exceção resulta em árvores muito mais utilizáveis.

Aqui está um código que altera a seleção durante o clique com o botão direito:

  private void tree_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
  {
     // only need to change selected note during right-click - otherwise tree does
     // fine by itself
     if ( e.Button == MouseButtons.Right )
     {         
        Point pt = new Point( e.X, e.Y );
        tree.PointToClient( pt );

        TreeNode Node = tree.GetNodeAt( pt );
        if ( Node != null )
        {
           if ( Node.Bounds.Contains( pt ) )
           {
              tree.SelectedNode = Node;
              ResetContextMenu();
              contextMenuTree.Show( tree, pt );
           }
        }
     }
  }

Revivendo esta questão porque acho que esta é uma solução muito melhor.Eu uso o NodeMouseClick evento em vez disso.

void treeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if( e.Button == MouseButtons.Right )
    {
        tree.SelectedNode = e.Node;
    }
}

Semelhante à resposta de Marcus, esta foi a solução que achei que funcionou para mim:

private void treeView_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        treeView.SelectedNode = treeView.GetNodeAt(e.Location);
    }
}

Você não precisa mostrar o menu de contexto se configurá-lo para cada nó individual da seguinte forma:

TreeNode node = new TreeNode();
node.ContextMenuStrip = contextMenu;

Então, dentro do evento Opening do ContextMenu, a propriedade TreeView.SelectedNode refletirá o nó correto.

Esta é uma pergunta muito antiga, mas ainda achei útil.Estou usando uma combinação de algumas das respostas acima, porque não quero que o nó clicado com o botão direito se torne o nó selecionado.Se eu tiver o nó raiz selecionado e quiser excluir um de seus filhos, não quero que o filho seja selecionado quando eu excluí-lo (também estou fazendo algum trabalho no selectedNode que não quero que aconteça à direita). clique).Aqui está minha contribuição:

// Global Private Variable to hold right-clicked Node
private TreeNode _currentNode = new TreeNode();

// Set Global Variable to the Node that was right-clicked
private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Right)
        _currentNode = e.Node;
}

// Do something when the Menu Item is clicked using the _currentNode
private void toolStripMenuItem_Clicked(object sender, EventArgs e)
{
    if (_currentNode != null)
        MessageBox.Show(_currentNode.Text);
}

Se você deseja que o menu de contexto dependa do item selecionado, a melhor coisa a fazer é usar o código do Jonesinator para selecionar o item clicado.O conteúdo do menu de contexto pode então depender do item selecionado.

Selecionar o item primeiro, em vez de usá-lo apenas no menu de contexto, oferece algumas vantagens.A primeira é que o usuário tenha uma indicação visual de onde clicou e, portanto, a qual item o menu está associado.A segunda é que desta forma é muito mais fácil manter a compatibilidade com outros métodos de invocar o menu de contexto (por exemplo,atalhos do teclado).

Aqui está como eu faço isso.

private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Right)
        e.Node.TreeView.SelectedNode = e.Node;
}

Outra opção que você pode usar é ter uma variável global que contenha o nó selecionado.Você só precisaria usar o TreeNodeMouseClickEventArgs.

public void treeNode_Click(object sender, TreeNodeMouseClickEventArgs e)
{
    _globalVariable = e.Node;
}

Agora você tem acesso a esse nó e suas propriedades.

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