我正在开发一个winform,在我的UI上有一个树视图,我发现即使我没有用鼠标点击节点也会突出显示treenode(例如,当我点击以下内容时,Node1会突出显示位置),但我真的不喜欢这种行为,因为我想在我没有点击treenode时显示不同的上下文菜单
+根节点
|_ Node1 [ Right Click Here, Node1 will be highlighted] | |_ Node2 [ Right Click Here, Node2 will be highlighted]
答案 0 :(得分:4)
对Kevin Wienhold的回答发表评论,您只想让用户点击树视图的空白区域并取消选择任何选定的节点。
您可以通过处理TreeView
控件的MouseDown
event,并将SelectedNode
property设置为null
来完成此操作,如果鼠标点击了某个位置不包含节点。例如,您可以使用以下代码:
private void myTreeView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (myTreeView.HitTest(e.Location).Node == null)
{
myTreeView.SelectedNode = null;
}
}
利用HitTest
method确定哪个节点位于特定点,将鼠标事件的位置指定为要测试的点。当用户 点击它们时,您不需要像往常一样选择任何其他代码;由TreeView
自动处理。
编辑:正如我对问题的评论所表明的那样,我仍然非常不清楚你要在这里完成什么。如果您真的有兴趣在节点侧面的空白区域中按住鼠标右键时阻止节点暂时突出显示,那么事情会变得复杂一些。
我之前已经研究过这个问题,而棘手的部分是在按住鼠标按钮时没有接收到窗口消息,至少在移动鼠标之前是这样(在这种情况下,节点不再是无论如何选择)。这种行为显然是由操作系统决定的,并且不容易使用标准的.NET提供的事件进行覆盖。您可以尝试全天取消MouseDown
事件中单击右侧按钮,但是在您的控件中引发此事件之前,Windows正在选择该节点(请记住.NET提供的控件,如TreeView
和ListView
只是围绕Windows API提供的相同控件的包装器,它显然实现了“选择节点同时按下按钮”行为本身。)
的工作原理是覆盖派生TreeView
控件中的WndProc
,并处理WM_RBUTTONDOWN
message。但请注意,即使将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);
}
}
您可以在自定义RightMouseClick
课程中raise your own TreeView
来回复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);
}
}
答案 1 :(得分:1)
试试这个
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;
}
}
答案 2 :(得分:1)
我找到了另一种方法来防止当用户没有点击节点时突出显示节点,并且我只在为每个节点添加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;
}
答案 3 :(得分:0)
如果我理解正确,如果用户点击TreeView中的空白区域,则不希望选择任何节点。 您可以通过处理Tree的MouseDown-Event并将树的SelectedNode属性设置为TreeView.GetNodeAt(e.Location)来实现此目的。