即使我没有右键单击节点,树视图节点也会突出显示
我在winform上工作,在我的UI上有一个树视图,我发现treenode会突出显示,即使我没有用鼠标点击节点(例如,当我点击下面的位置时,Node1会突出显示),但我真的不喜欢这种行为,因为我想在没有点击treenode时显示不同的上下文菜单
+根节点
|_ Node1 [ Right Click Here, Node1 will be highlighted] | |_ Node2 [ Right Click Here, Node2 will be highlighted]
将评论转到Kevin Wienhold的答案,您只想让用户点击树视图的空白区域并取消选择任何选定的节点。
您可以通过处理TreeView
控件的MouseDown
事件来执行此操作,并且如果在不包含节点的位置上单击鼠标,则将SelectedNode
属性设置为null
。 例如,您可以使用以下代码:
private void myTreeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if (myTreeView.HitTest(e.Location).Node == null) { myTreeView.SelectedNode = null; } }
这利用了HitTest
方法来确定哪个节点位于特定点,将鼠标事件的位置指定为要测试的点。 当用户点击它们时,您不需要像往常一样选择任何其他代码; 由TreeView
自动处理。
编辑:正如我对这个问题的评论所表明的那样,我仍然非常不清楚你要在这里完成什么。 如果您实际上有兴趣在节点侧面的空白区域中按住鼠标右键时阻止节点暂时突出显示,则事情会变得复杂一些。
我之前已经研究过这个问题,而棘手的部分是在按住鼠标按钮时没有接收到窗口消息,至少在移动鼠标之前是这样(在这种情况下,不再选择节点) 。 这种行为显然是由操作系统决定的,并且不容易使用标准的.NET提供的事件来覆盖。 您可以尝试整天取消单击MouseDown
事件中的右键,但是在您的控件中引发此事件之前,Windows正在选择该节点(请记住,.NET提供的控件如TreeView
和ListView
是简单地围绕Windows API提供的相同控件包装,这显然实现了这个“选择节点同时按下按钮”行为本身)。
但是,在派生的TreeView
控件中覆盖WndProc
并处理WM_RBUTTONDOWN
消息的工作原理是什么。 但请注意,即使将SelectedNode
属性设置为null
也不起作用,因为直到Windows自动选择节点作为对单击鼠标右键的响应之后才会处理 – 无论你做什么,你必须防止基数TreeView
控件从接收WM_RBUTTONDOWN
消息。 所以,你有几个选择如何处理这个:
-
您可以通过使用
return
语句提前终止来取消右键单击消息。 当然,这意味着您无法在MouseDown
处理程序中处理此事件,因为它实际上从未传递给控件! 因此,如果您想显示弹出式上下文菜单,这可能不适合您。public class NewTreeView : System.Windows.Forms.TreeView { protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_RBUTTONDOWN = 0x204; if (m.Msg == WM_RBUTTONDOWN) { return; } base.WndProc(ref m); } }
-
您可以在重写的
WndProc
方法中显示上下文菜单作为对WM_RBUTTONDOWN
消息的响应,然后从方法return
,而不允许基类处理消息。 这与第一个解决方案完全相同(防止右键单击事件导致节点显示为选中),但它确实允许您在右键单击时显示上下文菜单(或执行任何其他操作)发生。 当然,它确实意味着所有相关代码都必须包含在TreeView
控件的子类中,而不是在表单的UI代码中处理,这可能对您不方便也可能不方便。public class NewTreeView : System.Windows.Forms.TreeView { protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_RBUTTONDOWN = 0x204; if (m.Msg == WM_RBUTTONDOWN) { //Create and show a context menu var myContextMenu = new ContextMenuStrip(); myContextMenu.Items.Add("First Item"); myContextMenu.Items.Add("Second Item"); return; } base.WndProc(ref m); } }
-
您可以从自定义
TreeView
类中引发自己的RightMouseClick
事件,作为对WM_RBUTTONDOWN
消息的响应,然后您可以根据需要从表单的UI代码处理该消息。 通过不将WM_RBUTTONDOWN
消息传递给基础TreeView
控件类,这实现了与前两个建议相同的目标,但允许您在表单的UI代码中处理右键单击事件,而不必将所有逻辑放入子类控件的WndProc
。public class NewTreeView : System.Windows.Forms.TreeView { protected override void WndProc(ref System.Windows.Forms.Message m) { const int WM_RBUTTONDOWN = 0x204; if (m.Msg == WM_RBUTTONDOWN) { //Raise your custom event OnRightMouseClick(new EventArgs()); return; } base.WndProc(ref m); } }
试试这个
void treeView1_MouseDown(object sender, MouseEventArgs e) { TreeViewHitTestInfo h = treeView1.HitTest(e.Location); if (h.Location != TreeViewHitTestLocations.Label && h.Location!= TreeViewHitTestLocations.None ) { treeView1.SelectedNode = null; } }
我找到了另一种方法来防止当用户没有点击节点时突出显示节点,并且我只在为每个节点添加BackColor和ForeColor时将其添加到树中
newNode.BackColor = treeview1.BackColor; newNode.ForeColor = treeview1.ForeColor; treeview1.Nodes.Add(newNode);
然后在MouseDown事件中,将SelectedNode属性设置如下
private void treeView1_MouseDown(object sender, MouseEventArgs e) { TreeNode Node = treeView1.GetNodeAt(e.Location); if (Node != null && Node.Bounds.Contains(e.Location)) treeView1.SelectedNode = Node; else treeView1.SelectedNode = null; }
如果我理解正确,如果用户单击TreeView中的空白区域,则不希望选择任何节点。 您可以通过处理Tree的MouseDown-Event并将树的SelectedNode属性设置为TreeView.GetNodeAt(e.Location)来实现。