我正在将VB6应用程序迁移到.Net,我们必须始终提供类似功能。一种形式是带有三个级别节点的复选框的树视图。第一级仅用于将下一级别分组,并且它们不可检查。第二级节点可由用户检查,当检查或取消选中时,其所有子节点都遵循。在所有级别,单击节点或其复选框将意味着它被选中,无论检查状态是否受到影响。
第三个级别是问题的症结所在(尽管问题本身在所有树视图复选框中都有显示):此级别包含两个“类型”的节点,一个可以由用户检查和取消选中(如果检查了父级)一种类型,无论父级的状态如何,用户都无法检查或取消选中,但其状态与其父级的状态相同。
在正常使用中,这一切都按预期工作。但是,如果您快速单击其中一个第三级节点(不应该是可以直接检查的)两次,它似乎会更改其检查状态。但是,如果您检查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
运行它,然后单击节点ONCE。单击按钮1,它将告诉您节点文本及其已检查状态。现在单击相同的节点复选框两次,快速,观察复选标记的状态,然后再次单击按钮1。你会明白我的意思。按钮2生成一组新的树节点。
答案 0 :(得分:5)
是的,这是本机TreeView控件的Vista版本引入的错误。当它看到双击事件时,它将自动切换项目的检查状态。在没有告诉.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