查找在上下文菜单下单击的节点

发布于 2024-07-04 01:17:40 字数 128 浏览 4 评论 0原文

如何找出树列表中的哪个节点已激活上下文菜单? 例如,右键单击节点并从菜单中选择一个选项。

我无法使用 TreeViews 的 SelectedNode 属性,因为该节点仅被右键单击而未被选中。

How can I find out which node in a tree list the context menu has been activated? For instance right-clicking a node and selecting an option from the menu.

I can't use the TreeViews' SelectedNode property because the node is only been right-clicked and not selected.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

蓝礼 2024-07-11 01:17:40

重新提出这个问题是因为我发现这是一个更好的解决方案。
我改用 NodeMouseClick 事件。

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

Reviving this question because I find this to be a much better solution.
I use the NodeMouseClick event instead.

void treeview_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if( e.Button == MouseButtons.Right )
    {
        tree.SelectedNode = e.Node;
    }
}
对风讲故事 2024-07-11 01:17:40

这是一个非常古老的问题,但我仍然发现它很有用。 我使用上面一些答案的组合,因为我不希望右键单击的节点成为 selectedNode。 如果我选择了根节点并想要删除它的一个子节点,那么我不希望在删除它时选择该子节点(我还在 selectedNode 上做了一些工作,但我不希望在右侧发生这种情况 -点击)。 这是我的贡献:

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

This is a very old question, but I still found it useful. I am using a combination of some of the answers above, because I don't want the right-clicked node to become the selectedNode. If I have the root node selected and want to delete one of it's children, I don't want the child selected when I delete it (I am also doing some work on the selectedNode that I don't want to happen on a right-click). Here is my contribution:

// 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);
}
救赎№ 2024-07-11 01:17:40

与马库斯的答案类似,这是我发现对我有用的解决方案:

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

如果将其设置为每个单独的节点,则不需要自己显示上下文菜单,如下所示:

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

然后在 ContextMenu 的 Opening 事件中,TreeView.SelectedNode 属性将反映正确的节点。

Similar to Marcus' answer, this was the solution I found worked for me:

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

You need not show the context menu yourself if you set it to each individual node like so:

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

Then inside the ContextMenu's Opening event, the TreeView.SelectedNode property will reflect the correct node.

倾听心声的旋律 2024-07-11 01:17:40

这是我的解决方案。 将此行放入 TreeView 的 NodeMouseClick 事件中:

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

Here is my solution. Put this line into NodeMouseClick event of the TreeView:

 ((TreeView)sender).SelectedNode = e.Node;
梦过后 2024-07-11 01:17:40

我发现标准的 Windows 树视图行为选择行为非常烦人。 例如,如果您使用资源管理器并右键单击节点并单击“属性”,则会突出显示该节点并显示您单击的节点的属性对话框。 但是,当您从对话框返回时,突出显示的节点是您右键单击之前先前选择/突出显示的节点。 我发现这会导致可用性问题,因为我永远对我是否在正确的节点上操作感到困惑。

因此,在许多 GUI 中,我们通过右键单击更改选定的树节点,以免造成混淆。 这可能与像 Explorer 这样的标准 iwndos 应用程序不同(出于可用性原因,我倾向于在标准窗口应用程序之后强烈建模我们的 GUI 行为),我相信这一例外情况会产生更多可用的树。

以下是一些在右键单击期间更改选择的代码:

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

I find the standard windows treeview behavior selection behavior to be quite annoying. For example, if you are using Explorer and right click on a node and hit Properties, it highlights the node and shows the properties dialog for the node you clicked on. But when you return from the dialog, the highlighted node was the node previously selected/highlighted before you did the right-click. I find this causes usability problems because I am forever being confused on whether I acted on the right node.

So in many of our GUIs, we change the selected tree node on a right-click so that there is no confusion. This may not be the same as a standard iwndos app like Explorer (and I tend to strongly model our GUI behavior after standard window apps for usabiltiy reasons), I believe that this one exception case results in far more usable trees.

Here is some code that changes the selection during the right click:

  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 );
           }
        }
     }
  }
瞎闹 2024-07-11 01:17:40

您可以向 TreeView 添加鼠标单击事件,然后使用 GetNodeAt 根据 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);
        }
    }
}

You can add a mouse click event to the TreeView, then select the correct node using GetNodeAt given the mouse coordinates provided by the 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);
        }
    }
}
扶醉桌前 2024-07-11 01:17:40

您可以使用的另一个选项是使用一个包含所选节点的全局变量。 您只需要使用TreeNodeMouseClickEventArgs

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

现在您可以访问该节点及其属性。

Another option you could run with is to have a global variable that has the selected node. You would just need to use the TreeNodeMouseClickEventArgs.

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

Now you have access to that node and it's properties.

岁吢 2024-07-11 01:17:40

我想提出一种使用单击事件的替代方法,即使用上下文菜单的 Opened 事件:

private void Handle_ContextMenu_Opened(object sender, EventArgs e)
{
    TreeViewHitTestInfo info = treeview.HitTest(treeview.PointToClient(Cursor.Position));
    TreeNode contextNode;

    // was there a node where the context menu was opened?
    if (info != null && info.Node != null)
    {
        contextNode = info.Node;
    }

    // Set the enabled states of the context menu elements
    menuEdit.Enabled = contextNode != null;
    menuDelete.Enabled = contextNode != null;
}

我可以看到这具有以下优点:

  • 它不会更改选定的节点
  • 不需要单独的事件处理程序存储目标节点实例
  • 如果用户右键单击 TreeView 中的空白区域,可以禁用菜单项

注意:如果您担心用户在打开菜单时可能已经移动了鼠标,可以使用 Opening 事件改为。

I would like to propose an alternative to using the click events, using the context menu's Opened event:

private void Handle_ContextMenu_Opened(object sender, EventArgs e)
{
    TreeViewHitTestInfo info = treeview.HitTest(treeview.PointToClient(Cursor.Position));
    TreeNode contextNode;

    // was there a node where the context menu was opened?
    if (info != null && info.Node != null)
    {
        contextNode = info.Node;
    }

    // Set the enabled states of the context menu elements
    menuEdit.Enabled = contextNode != null;
    menuDelete.Enabled = contextNode != null;
}

This has the following advantages that I can see:

  • It does not change the selected node
  • No separate event handler needed to store the target node instance
  • Can disable menu items if the user right-clicks empty space in the TreeView

Note: if you worry that the user may have already moved the mouse by the time the menu is opened, it is possible to use the Opening event instead.

海之角 2024-07-11 01:17:40

我是这样做的。

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

Here is how I do it.

private void treeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Right)
        e.Node.TreeView.SelectedNode = e.Node;
}
猥琐帝 2024-07-11 01:17:40

如果您希望上下文菜单依赖于所选项目,我认为最好的做法是使用 Jonesinator 的代码来选择单击的项目。 然后,您的上下文菜单内容可以取决于所选项目。

首先选择该项目而不是仅将其用于上下文菜单有一些优点。 第一个是用户可以通过视觉指示知道他点击了哪一个,从而知道菜单与哪个项目相关联。 第二个是,通过这种方式,与调用上下文菜单的其他方法(例如键盘快捷键)保持兼容要容易得多。

If you want the context menu to be dependent on the selected item you're best move I think is to use Jonesinator's code to select the clicked item. Your context menu content can then be dependent on the selected item.

Selecting the item first as opposed to just using it for the context menu gives a few advantages. The first is that the user has a visual indication as to which he clicked and thus which item the menu is associated with. The second is that this way it's a hell of a lot easier to keep compatible with other methods of invoking the context menu (e.g. keyboard shortcuts).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文