vb.net - 多次快速单击时复选框无法正常工作
问题描述
这段代码的作用:
如果选中/取消选中父节点,则还要选中/取消选中所有子节点。
如果只选中一个子节点,还要检查父节点。
Private Sub TreeView1_AfterCheck(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterCheck If updatingTreeView Then Return updatingTreeView = True CheckNode(e.Node, e.Node.Checked) HasCheckedChildNode = 0 updatingTreeView = False End Sub
Private Sub CheckNode(node As TreeNode, isChecked As Boolean) If node.Parent IsNot Nothing Then HasCheckedNode(node.Parent) If Not isChecked And HasCheckedChildNode > 0 Then Return node.Parent.Checked = isChecked ElseIf node.Parent Is Nothing Then For Each cn As TreeNode In node.Nodes cn.Checked = isChecked Next End If End Sub
Private Sub HasCheckedNode(node As TreeNode) For Each cn As TreeNode In node.Nodes If cn.Checked = True Then HasCheckedChildNode += 1 ElseIf cn.Checked = False Then HasCheckedChildNode -= 0 End If Next End Sub
这段代码工作正常。
问题:
当我快速单击时,某些复选框被选中,而有些则没有。例如,有时我检查了父节点,但所有子节点仍未选中。有时父节点未选中,但其子节点仍处于选中状态。
请检查示例图像:
请问这个怎么解决,是不是我电脑的问题?
解决方案
发生这种情况是因为默认情况下 TreeView 不会Check
在鼠标双击复选框区域时切换 TreeNode 对象的属性。您需要拦截WM_LBUTTONDBLCLK
消息,获取TreeViewHitTestInfo
双击点,Check
如果双击点超过复选框,则切换属性。
这是一个自定义的 TreeView,它也解决了主要问题,选中/取消选中分支的父节点和子节点,只需为此启用AutoCheckParents
和/或AutoCheckChildren
属性。
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
<DesignerCategory("Code")>
Public Class DoubleClickCheckTreeView
Inherits TreeView
#Region "Properties"
<Category("Behavior"),
DefaultValue(False)>
Public Property AutoCheckParents As Boolean = False
<Category("Behavior"),
DefaultValue(False)>
Public Property AutoCheckChildren As Boolean = False
#End Region
#Region "Overrides"
'Enable DoubleBuffered to reduce the flickering.
Protected Overrides Sub OnHandleCreated(e As EventArgs)
SendMessage(Handle,
TVM_SETEXTENDEDSTYLE,
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER),
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER))
MyBase.OnHandleCreated(e)
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_LBUTTONDBLCLK AndAlso CheckBoxes Then
Dim x As Integer = m.LParam.ToInt32() And &HFFFF
Dim y As Integer = (m.LParam.ToInt32 >> 16) And &HFFFF
Dim ht As TreeViewHitTestInfo = HitTest(x, y)
If ht.Node IsNot Nothing AndAlso
ht.Location = TreeViewHitTestLocations.StateImage Then
OnBeforeCheck(New TreeViewCancelEventArgs(ht.Node,
False,
TreeViewAction.ByMouse))
ht.Node.Checked = Not ht.Node.Checked
OnAfterCheck(New TreeViewEventArgs(ht.Node, TreeViewAction.ByMouse))
m.Result = IntPtr.Zero
Return
End If
End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub OnAfterCheck(e As TreeViewEventArgs)
MyBase.OnAfterCheck(e)
If e.Action = TreeViewAction.Unknown OrElse
Not CheckBoxes Then Return
If AutoCheckParents Then
Dim p = e.Node.Parent
While p IsNot Nothing
p.Checked = p.Nodes.Cast(Of TreeNode).Any(Function(x) x.Checked)
p = p.Parent
End While
End If
If AutoCheckChildren Then
For Each tn As TreeNode In GetNodes(e.Node)
tn.Checked = e.Node.Checked
Next
End If
End Sub
#End Region
#Region "Private Methods"
Private Iterator Function GetNodes(node As TreeNode) As IEnumerable(Of TreeNode)
For Each n As TreeNode In node.Nodes
Yield n
For Each c As TreeNode In GetNodes(n)
Yield c
Next
Next
End Function
#End Region
#Region "API"
Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
Private Const TVM_GETEXTENDEDSTYLE As Integer = &H1100 + 45
Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
Private Const WM_LBUTTONDBLCLK As Integer = &H203
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wp As IntPtr,
ByVal lp As IntPtr) As IntPtr
End Function
#End Region
End Class
- 向您的项目添加一个新类并粘贴此代码。
- 重建。
- 删除 DoubleClickCheckTreeView 的实例或更改设计器中现有默认 TreeView 的类型。
有关的
◉ TreeView、Windows 窗体中的 AfterCheck 和 AfterSelect 事件(c#)
推荐阅读
- java - 尝试将 JBoss 6.3 迁移到 WildFly 10 时出现错误 java.lang.NoClassDefFoundError: org/jboss/resteasy/core/ResourceMethod
- java - 扫描仪在 Java 中返回空字符串
- prometheus - 如何在 Prometheus 中找到具有特定标签的缺失指标?
- powerbi - Power Query 中的 Listagg 等效项 - M
- reactjs - 如何修复“(0,_reactNativeRedash.withTransition)不是函数”错误?
- excel - 有一个复选框将值添加到具有现有值的单元格
- r - 如何将具有坐标列表(MultliLineString)的列转换为R上的sf/st对象?
- embedded - 覆盖 SD 分区布局的 WKS_FILE
- java - 如何从存储库访问和返回 AsyncTask 的结果?
- heroku - 如何在 HerokuApp 上访问 root 以使用 wget 命令