Pregunta

¿Cómo puedo saber en qué nodo de una lista de árbol se ha activado el menú contextual?Por ejemplo, hacer clic derecho en un nodo y seleccionar una opción del menú.

No puedo usar TreeViews SelectedNode propiedad porque solo se hizo clic derecho en el nodo y no se seleccionó.

¿Fue útil?

Solución

Puede agregar un evento de clic del mouse a TreeView y luego seleccionar el nodo correcto usando GetNodeAt dadas las coordenadas del mouse proporcionadas por 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);
        }
    }
}

Otros consejos

Aquí está mi solución.Coloque esta línea en el evento NodeMouseClick de TreeView:

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

El comportamiento de selección del comportamiento de vista de árbol estándar de Windows me parece bastante molesto.Por ejemplo, si está utilizando el Explorador, hace clic derecho en un nodo y presiona Propiedades, resalta el nodo y muestra el cuadro de diálogo de propiedades del nodo en el que hizo clic.Pero cuando regresa del cuadro de diálogo, el nodo resaltado era el nodo previamente seleccionado/resaltado antes de hacer clic derecho.Creo que esto causa problemas de usabilidad porque siempre estoy confundido sobre si actué en el nodo correcto.

Entonces, en muchas de nuestras GUI, cambiamos el nodo del árbol seleccionado al hacer clic derecho para que no haya confusión.Puede que esto no sea lo mismo que una aplicación iwndos estándar como Explorer (y tiendo a modelar fuertemente el comportamiento de nuestra GUI a partir de aplicaciones de ventana estándar por razones de usabilidad), creo que este caso de excepción da como resultado árboles mucho más utilizables.

Aquí hay un código que cambia la selección durante el clic derecho:

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

Reviviendo esta pregunta porque creo que es una solución mucho mejor.Yo uso el NodeMouseClick evento en su lugar.

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

Similar a la respuesta de Marcus, esta fue la solución que encontré que funcionó para mí:

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

No es necesario que muestre el menú contextual usted mismo si lo configura para cada nodo individual de esta manera:

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

Luego, dentro del evento de apertura de ContextMenu, la propiedad TreeView.SelectedNode reflejará el nodo correcto.

Esta es una pregunta muy antigua, pero todavía la encuentro útil.Estoy usando una combinación de algunas de las respuestas anteriores, porque no quiero que el nodo en el que se hace clic con el botón derecho se convierta en el nodo seleccionado.Si tengo el nodo raíz seleccionado y quiero eliminar uno de sus hijos, no quiero que se seleccione el hijo cuando lo elimine (también estoy trabajando en el nodo seleccionado y no quiero que suceda a la derecha). hacer clic).Aquí está mi contribución:

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

Si desea que el menú contextual dependa del elemento seleccionado, creo que lo mejor que puede hacer es utilizar el código de Jonesinator para seleccionar el elemento en el que se hizo clic.El contenido del menú contextual puede entonces depender del elemento seleccionado.

Seleccionar el elemento primero en lugar de usarlo simplemente para el menú contextual ofrece algunas ventajas.La primera es que el usuario tiene una indicación visual de en qué hizo clic y, por tanto, a qué elemento está asociado el menú.La segunda es que de esta manera es muchísimo más fácil mantener la compatibilidad con otros métodos de invocar el menú contextual (p. ej.atajos de teclado).

Así es como lo hago.

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

Otra opción con la que podrías ejecutar es tener una variable global que tenga el nodo seleccionado.Sólo necesitarías usar el TreeNodeMouseClickEventArgs.

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

Ahora tiene acceso a ese nodo y sus propiedades.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top