2011-05-25 85 views
13

所以我有一个C#窗体窗体应用程序中的TreeView。我需要的是一些节点被“锁定”,以便它们不能根据参数进行检查(或未选中)。C#:如何避免双击事件发生TreeNode检查

我现在正在做的是这样的:

private void tv_local_BeforeCheck(object sender, TreeViewCancelEventArgs e) { 
    TNode node = (TNode)e.Node; 
    //if a part node, cancel the action. 
    if (node.Type == "Part") { 
     e.Cancel = true;  
    } 
    //if a locked node, cancel the action 
    if (node.Locked == true) { 
     e.Cancel = true; 
    } 
} 

该代码中的复选框的单次点击的伟大工程,但如果一个复选框用户双击,它仍然会检查/取消选中。

我曾尝试与nodeMouseDoubleClick事件打,但并没有真正的帮助,因为我无法取消的事件......

有任何想法在那里如何取消节点上的双击事件? ..还是其他什么? 谢谢

+0

你能后的您的DoubleClick活动处理程序的代码? – 2011-05-25 20:24:52

+0

我没有写在那里的东西。我不希望任何事情发生在双击... 如果我可以做e.Cancel = true,那将是doubleclick事件中的代码 – Toadums 2011-05-25 20:25:53

+0

您确定没有任何其他处理程序被设置吗?我刚刚尝试将树形视图拖放到窗体上,但无法重现问题(我正在使用VSTS2008) – 2011-05-25 20:37:16

回答

21

这是我认为TreeView中的一个错误(http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/9d717ce0-ec6b-4758-a357-6bb55591f956/)。您需要继承树视图的子类并禁用双击消息才能修复它。就像这样:

public class NoClickTree : TreeView 
    { 
     protected override void WndProc(ref Message m) 
     { 
      // Suppress WM_LBUTTONDBLCLK 
      if (m.Msg == 0x203) { m.Result = IntPtr.Zero; } 
      else base.WndProc(ref m); 
     }    
    }; 

当然,如果你这样做,你将不再能够使用在树视图其他的东西(如双双击比喻单击一个节点发动属性页, 或者其他的东西)。

+0

我曾经见过这个解决方案,但无法弄清楚如何使它工作 - 我没有意识到,我不得不创建一个新类并扩展treeview类。谢谢!! – Toadums 2011-05-25 20:43:32

+1

请记住,您必须在'Form1.Designer.cs'文件中将您的树视图初始化为'NoClickTree',而不是'Form1.cs',如[在此解释](http://stackoverflow.com/a/14758596/1677209) – T30 2014-08-04 15:22:53

+0

不错!这个bug一直是头疼! (至少对我来说) – 2014-09-11 05:37:47

0

尝试扩展TreeNode类并添加一个布尔属性来维护正确的checkedState。这样,当某人双击某个节点时,可以将该节点的选中状态重置为存储在该属性中的值。可能有更优雅的解决方案,但这是我能想到的最好的。

1

我用下面的代码,以防止检查根节点管理它:

private void MyTreeView_MouseUp(object sender, MouseEventArgs e) 
{ 
    // HACK: avoid to check root nodes (mr) 
    var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y)); 
    if (node != null && node.Parent == null) 
    BeginInvoke(new MouseEventHandler(TreeView_MouseUpAsync), sender, e); 
} 

private void TreeView_MouseUpAsync(object sender, MouseEventArgs e) 
{ 
    if (IsDisposed) 
     return; 

    var node = ((TreeView)sender).GetNodeAt(new Point(e.X, e.Y)); 
    node.Checked = false; 
} 
4

如果你希望你双击实际切换复选框,然后尝试:

protected override void WndProc(ref Message m) 
{ 
    // Filter WM_LBUTTONDBLCLK when we're showing check boxes 
    if (m.Msg == 0x203 && CheckBoxes) 
    { 
    // See if we're over the checkbox. If so then we'll handle the toggling of it ourselves. 
    int x = m.LParam.ToInt32() & 0xffff; 
    int y = (m.LParam.ToInt32() >> 16) & 0xffff; 
    TreeViewHitTestInfo hitTestInfo = HitTest(x, y); 

    if (hitTestInfo.Node != null && hitTestInfo.Location == TreeViewHitTestLocations.StateImage) 
    { 
     OnBeforeCheck(new TreeViewCancelEventArgs(hitTestInfo.Node, false, TreeViewAction.ByMouse)); 
     hitTestInfo.Node.Checked = !hitTestInfo.Node.Checked; 
     OnAfterCheck(new TreeViewEventArgs(hitTestInfo.Node, TreeViewAction.ByMouse)); 
     m.Result = IntPtr.Zero; 
     return; 
    } 
    } 

    base.WndProc(ref m); 
} 
+0

我用你的代码,它似乎工作。非常感谢。 – DonkeyMaster 2013-07-19 13:10:05

+0

完美的作品! – 2016-08-02 11:55:44