Domanda

Come posso sapere in quale nodo di un elenco ad albero è stato attivato il menu contestuale?Ad esempio, facendo clic con il pulsante destro del mouse su un nodo e selezionando un'opzione dal menu.

Non riesco a utilizzare TreeViews' SelectedNode proprietà perché sul nodo è stato solo fatto clic con il pulsante destro del mouse e non è stato selezionato.

È stato utile?

Soluzione

È possibile aggiungere un evento clic del mouse a TreeView, quindi selezionare il nodo corretto utilizzando GetNodeAt in base alle coordinate del mouse fornite da 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);
        }
    }
}

Altri suggerimenti

Ecco la mia soluzione.Inserisci questa riga nell'evento NodeMouseClick di TreeView:

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

Trovo che il comportamento di selezione del comportamento standard della visualizzazione ad albero di Windows sia piuttosto fastidioso.Ad esempio, se stai utilizzando Explorer e fai clic con il pulsante destro del mouse su un nodo e premi Proprietà, il nodo verrà evidenziato e verrà visualizzata la finestra di dialogo delle proprietà per il nodo su cui hai fatto clic.Ma quando torni dalla finestra di dialogo, il nodo evidenziato era il nodo precedentemente selezionato/evidenziato prima di fare clic con il pulsante destro del mouse.Trovo che questo causi problemi di usabilità perché sono sempre confuso sul fatto di aver agito sul nodo giusto.

Pertanto, in molte delle nostre GUI, modifichiamo il nodo dell'albero selezionato facendo clic con il pulsante destro del mouse in modo che non ci sia confusione.Questo potrebbe non essere lo stesso di un'app iwndos standard come Explorer (e tendo a modellare fortemente il nostro comportamento della GUI dopo le app di finestre standard per motivi di usabilità), credo che questo caso di eccezione si traduca in alberi molto più utilizzabili.

Ecco del codice che modifica la selezione durante il clic destro:

  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 );
           }
        }
     }
  }

Rilanciare questa domanda perché trovo che questa sia una soluzione molto migliore.Io uso il NodeMouseClick evento invece.

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

Simile alla risposta di Marcus, questa è stata la soluzione che ho trovato ha funzionato per me:

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

Non è necessario mostrare tu stesso il menu contestuale se lo imposti su ogni singolo nodo in questo modo:

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

Quindi, all'interno dell'evento Opening di ContextMenu, la proprietà TreeView.SelectedNode rifletterà il nodo corretto.

Questa è una domanda molto vecchia, ma l'ho comunque trovata utile.Sto utilizzando una combinazione di alcune delle risposte sopra, perché non voglio che il nodo cliccato con il tasto destro diventi il ​​selezionato Node.Se ho selezionato il nodo radice e desidero eliminare uno dei suoi figli, non voglio che il figlio venga selezionato quando lo elimino (sto anche facendo del lavoro sul nodo selezionato che non voglio che avvenga a destra- clic).Ecco il mio contributo:

// 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 vuoi che il menu contestuale dipenda dall'elemento selezionato, la mossa migliore, penso sia utilizzare il codice di Jonesinator per selezionare l'elemento su cui si è fatto clic.Il contenuto del menu contestuale può quindi dipendere dall'elemento selezionato.

Selezionare prima l'elemento invece di usarlo solo per il menu contestuale offre alcuni vantaggi.Il primo è che l'utente abbia un'indicazione visiva su cosa ha cliccato e quindi a quale voce è associato il menu.Il secondo è che in questo modo è molto più semplice mantenere la compatibilità con altri metodi di richiamo del menu contestuale (es.tasti rapidi).

Ecco come lo faccio.

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

Un'altra opzione con cui potresti eseguire è avere una variabile globale che abbia il nodo selezionato.Avresti solo bisogno di usare il file TreeNodeMouseClickEventArgs.

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

Ora hai accesso a quel nodo e alle sue proprietà.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top