2010-08-04 97 views
3

我正在将VB6应用程序迁移到.Net,我们必须始终提供类似功能的功能。在一种形式中是具有复选框的树形视图,其具有三个级别的节点。第一级仅用于将下一级分组,并且它们不可检查。第二级节点可由用户检查,当选中或取消选中时,其所有孩子都会效仿。无论检查状态是否受到影响,在所有级别,单击节点或其复选框都将意味着它被选中。.Net Treeview事件处理

第三个层次是问题的症结所在(尽管问题本身在所有treeview复选框中都有所体现):该层包含两个节点类型,一个可以由用户检查和取消选中(如果父类是检查)以及一种类型,无论父母的状态如何,用户都无法检查或取消选中,但其状态与其父母的状态相同。

在正常使用中,这一切都按预期工作。但是,如果您快速点击第三层节点之一(不应该直接检查)两次,它似乎会更改其检查状态。但是,如果您检查Checked属性的基础值,它将保持不受影响,因此它看起来只是一个显示问题。如果发现,这种异常将成为我们客户的一个问题,因为用户可能认为他们可以做一些他们不能导致昂贵混淆的事情。

我刚刚从这一想法的新鲜 - 有任何人观察到这种行为或知道它,并有解决方法/解决方案吗?我不禁感到我错过了一些非常明显的事情,但在一天半之后,我现在拥有隧道视野。这里有一些代码来演示这个问题。创建一个树状形式(大到足以看到发生了什么事情)和两个按钮,然后放弃这一在:

Private _node As TreeNode = Nothing 


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 

    MessageBox.Show(_node.Text & " : " & _node.Checked.ToString) 
    _node = Nothing 

End Sub 

Private Sub InitialiseTreeview() 

    TreeView1.Nodes.Clear() 

    Dim ran As New Random 
    Randomize() 

    For i As Int32 = 1 To 5 
     Dim TLNode As New TreeNode 
     Dim children As Int32 = 0 

     children = ran.Next(1, 5) 

     TLNode.Text = "Top Level Node " & i.ToString 

     For j As Int32 = 1 To children 
      TLNode.Nodes.Add("Child Node " & j.ToString) 
     Next 

     TreeView1.Nodes.Add(TLNode) 
    Next 

    TreeView1.ExpandAll() 
End Sub 

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    InitialiseTreeview() 
End Sub 


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
    InitialiseTreeview() 
End Sub 

运行它,然后单击一个节点上一次。点击按钮1,它会告诉你节点文本和它的检查状态。现在,快速点击相同节点复选框两次,观察复选标记的状态并再次单击按钮1。你会明白我的意思。按钮2生成一组新的树节点。

回答

5

是的,这是Vista本地TreeView控件引入的一个bug。当它看到双击事件时,它会自动切换项目的检查状态。如果不告诉.NET TreeView包装器,Before/AfterCheck事件将不会运行。这在.NET包装器中没有被修复,可能永远不会。

解决此错误需要防止本机控制看到双击消息。为您的项目添加一个新类并粘贴下面显示的代码。编译。将新的控件从工具箱的顶部拖放到窗体上,替换现有的TreeView。

Public Class MyTreeView 
    Inherits TreeView 

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
     '' Filter the WM_LBUTTONDBLCLK message 
     If m.Msg <> &H203 Then MyBase.WndProc(m) 
    End Sub 

End Class 
+0

谢天谢地 - 我以为我失去了理智。我已经实现了你的建议解决方案,它的工作原理绝对完美非常感谢您的快速响应和示例解决方法代码。如果我有足够的声望,我会投你的答案,但我还没有到那里! – 2010-08-05 11:11:49

+0

啊,突然我有足够的代表投票了! – 2010-08-05 11:16:39

+1

微软为什么不解决这个问题? – Andrew 2012-12-14 13:01:56