Найти узел, нажатый в контекстном меню

Как я могу узнать, какой узел в древовидном списке было активировано контекстное меню? Например, щелкнув узел правой кнопкой мыши и выбрав параметр в меню.

Я не могу использовать свойство SelectedNode TreeViews, потому что узел щелкается правой кнопкой мыши и не выбран.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
74
0
56 122
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Ответ принят как подходящий

Вы можете добавить событие щелчка мыши в 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);
        }
    }
}

Большое спасибо, у меня есть небольшое дополнение к решению: вы также можете использовать событие «_NodeMouseClick», которое дает вам «TreeNodeMouseClickEventArgs e», и в этом случае вы можете просто использовать e.Node и не беспокоиться о проверке является ли узел нулевым или нет.

SDM 09.07.2013 18:44

Я получил желаемый результат с событием MouseDown вместо MouseUp.

Javier 31.07.2013 16:53

Если вы хотите, чтобы контекстное меню зависело от выбранного элемента, лучше всего использовать код Jonesinator для выбора элемента, по которому щелкнули мышью. В этом случае содержимое контекстного меню может зависеть от выбранного элемента.

Выбор элемента первым, а не просто его использование для контекстного меню дает несколько преимуществ. Во-первых, у пользователя есть визуальная индикация того, на что он щелкнул и, следовательно, с каким элементом связано меню. Во-вторых, таким образом намного проще поддерживать совместимость с другими методами вызова контекстного меню (например, сочетаниями клавиш).

Я считаю, что стандартное поведение выбора поведения в виде дерева в Windows довольно раздражает. Например, если вы используете проводник и щелкаете правой кнопкой мыши узел и нажимаете «Свойства», он выделяет узел и отображает диалоговое окно свойств для узла, на котором вы щелкнули. Но когда вы вернетесь из диалогового окна, выделенный узел был ранее выбранным / выделенным до того, как вы щелкнули правой кнопкой мыши. Я считаю, что это вызывает проблемы с удобством использования, потому что я всегда не понимаю, действовал ли я на правильном узле.

Поэтому во многих наших графических интерфейсах мы изменяем выбранный узел дерева щелчком правой кнопки мыши, чтобы не возникало путаницы. Это может быть не то же самое, что и стандартное приложение iwndos, такое как Explorer (и я склонен строго моделировать наше поведение графического интерфейса после стандартных оконных приложений по причинам удобства использования), я считаю, что этот единственный случай исключения приводит к гораздо более пригодным для использования деревьям.

Вот код, который изменяет выбор при щелчке правой кнопкой мыши:

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

Для меня это лучшее решение, потому что оно фактически выбирает узел, на котором вы щелкнули.

CAD bloke 13.01.2012 06:07

Вот мое решение. Поместите эту строку в событие NodeMouseClick TreeView:

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

Аргументы события мыши не имеют .Node

CAD bloke 13.01.2012 06:04

Да, но TreeNodeMouseClickEventArgs (которые передаются в событие NodeMouseClick) делают. Итак, мое решение работает и не является чрезмерно сложным, как некоторые другие решения.

deej 21.06.2012 22:17

Подобно ответу Маркуса, это решение, которое я нашел, сработало для меня:

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 свойство TreeView.SelectedNode будет отражать правильный узел.

Возобновляя этот вопрос, я считаю, что это гораздо лучшее решение. Вместо этого я использую событие NodeMouseClick.

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

Мне это тоже нравится намного больше.

Joey Novak 01.02.2017 01:39

Вот как я это делаю.

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

Это очень старый вопрос, но я все же нашел его полезным. Я использую комбинацию некоторых из приведенных выше ответов, потому что я не хочу, чтобы узел, щелкнувший правой кнопкой мыши, стал 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);
}

Другой вариант, с которым вы можете работать, - это иметь глобальную переменную с выбранным узлом. Вам просто нужно использовать TreeNodeMouseClickEventArgs.

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

Теперь у вас есть доступ к этому узлу и его свойствам.

Я хотел бы предложить альтернативу использованию событий щелчка, используя событие 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.

Другие вопросы по теме