问题描述
我正在将 VB6 应用程序迁移到 .Net,我们必须始终提供同类功能.一种形式是带有复选框的树视图,该复选框具有三个级别的节点.第一级仅用于对下一级进行分组,并且它们是不可检查的.用户可以通过检查或取消选中其所有子女遵循适合的第二级节点.在所有级别,单击一个节点或其复选框将意味着它被选中,无论检查状态是否受到影响.
I am in the process of migrating a VB6 app to .Net and we must provide like-for-like functionality at all times. In one form is a treeview with checkboxes that has three levels of nodes. The first level serves only to group the next level down and they are not checkable. The second level nodes are checkable by the user and when checked or unchecked all its children follow suit. At all levels, clicking a node or its checkbox will mean it becomes selected, regardless of whether or not the check state is affected.
第三层是问题的症结所在(尽管问题本身在所有树视图复选框上都有体现):这一层包含两种类型"的节点,一种可以由用户选中和取消选中(如果选中了父节点) 和一种类型,无论父级的状态如何,用户都无法选中或取消选中,但其状态反映了其父级的状态.
The third level is the crux of the problem (although the issue itself manifests on all treeview checkboxes): this level contains two 'types' of node, one which can be checked and unchecked by the user (if the parent is checked) and one type which cannot be checked or unchecked by the user regardless of the state of the parent, but its state mirrors that of its parent.
在正常使用中,这一切都按预期工作.但是,如果您快速单击第三级节点之一(不应直接检查)两次,它似乎会更改其检查状态.但是,如果您检查 Checked 属性的基础值,它仍然不受影响,因此它似乎只是一个显示问题.如果发现此异常,我们的客户将面临问题,因为用户可能认为他们可以做一些他们无法做到的事情,从而导致代价高昂的混乱.
In normal use this all works as expected. However, if you quickly click one of the third level nodes (which is not supposed to be directly checkable) twice, it appears to change its check state. But if you examine the underlying value of the Checked property, it remains unaffected, so it seems it is simply a display issue. If discovered, this anomaly will be an issue for our clients as users may think they can do something that they cannot leading to expensive confusion.
我对此一无所知 - 有没有其他人观察到或知道这种行为,是否有解决方法/解决方案?我不禁觉得我错过了一些非常明显的东西,但在一天半之后,我现在有了隧道视觉.这里有一些代码来演示这个问题.创建一个带有树视图(大到可以查看发生了什么)和两个按钮的表单,然后将其放入:
I am fresh out of ideas on this one - has anyone else observed this behaviour or know about it and are there workarounds/solutions to it? I can't help feeling I've missed something really obvious but after a day and a half I now have tunnel vision. Here's some code to demonstrate the problem. Create a form with a treeview (big enough to see what's going on) and two buttons then drop this in:
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 生成一组新的树节点.
Run it, and click on a node ONCE. Click Button 1 and it will tell you the node text and it's checked state. Now click the same nodes checkbox twice, fast, observe the state of the checkmark and click button 1 again. You'll see what I mean. Button 2 generates a fresh set of tree nodes.
推荐答案
是的,这是原生TreeView控件的Vista版本引入的一个bug.当它看到双击事件时,它会自动切换项目的检查状态.如果不告诉 .NET TreeView 包装器,Before/AfterCheck 事件将不会运行..NET 包装器中尚未修复此问题,并且可能永远不会修复.
Yes, this is a bug introduced by the Vista version of the native TreeView control. When it sees the double-click event, it will automatic toggle the check state of the item. Without telling the .NET TreeView wrapper about it, the Before/AfterCheck event won't run. This hasn't been fixed in the .NET wrapper and probably never will.
解决此错误需要阻止本机控件看到双击消息.向您的项目添加一个新类并粘贴如下所示的代码.编译.将新控件从工具箱顶部拖放到表单上,替换现有的 TreeView.
Working around this bug requires preventing the native control from seeing the double-click message. Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form, replacing the existing 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
这篇关于.Net Treeview 事件处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!