多次快速单击时复选框无法正常工作 [英] CheckBox not work properly when clicked on quickly multiple times
问题描述
这段代码的作用:
如果父节点被选中/取消选中,还要选中/取消选中所有子节点.
If parent node is checked/unchecked, also check/uncheck all child nodes.
如果只检查了一个子节点,还要检查父节点.
If just one child node is checked, also check parent node.
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)如果 node.Parent IsNot Nothing 那么HasCheckedNode(node.Parent)如果没有 isChecked 并且 HasCheckedChildNode > 0 然后返回node.Parent.Checked = isCheckedElseIf node.Parent Is Nothing Then对于每个 cn 作为 TreeNode 在 node.Nodescn.Checked = isChecked下一个万一结束子
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
私有子HasCheckedNode(node As TreeNode)对于每个 cn 作为 TreeNode 在 node.Nodes如果 cn.Checked = True 那么HasCheckedChildNode += 1ElseIf cn.Checked = False 那么HasCheckedChildNode -= 0万一下一个结束子
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
此代码工作正常.
问题:
当我快速点击时,有些复选框被选中,有些没有例如.有时我检查了父节点,但所有子节点仍然未选中.有时父节点未选中但其子节点仍选中.
When I clicks quickly some of the checkboxes are checked and some no E.g. Sometimes I checked the parent node but all child nodes still remain unchecked. Sometimes the parent node is unchecked but its child nodes still checked.
请检查示例图片:
如何解决这个问题,这是我电脑的问题吗?
How to solve this, is this a problem with my PC?
推荐答案
发生这种情况是因为 TreeView 默认情况下不会在鼠标双击复选框时切换 TreeNode 对象的 Check
属性区域.您需要拦截WM_LBUTTONDBLCLK
消息,获取双击点的TreeViewHitTestInfo
,如果双击点超过了,则切换Check
属性复选框.
That happens because the TreeView by default doesn't toggle the Check
property of the TreeNode objects on mouse double click over the check box area. You need to intercept the WM_LBUTTONDBLCLK
messages, get TreeViewHitTestInfo
of the double clicked point, and toggle the Check
property if the double clicked point is over the check box.
这是一个自定义的 TreeView,它也解决了主要问题,检查/取消检查分支的父节点和子节点,只需启用 AutoCheckParents
和/或 AutoCheckChildren
属性.
Here's a custom TreeView for that, also it solves the main issue, checking/unchecking the parent and child nodes of the branch, just enable the AutoCheckParents
and/or AutoCheckChildren
properties for that.
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 窗体 (c#) 中的 AfterCheck 和 AfterSelect 事件
这篇关于多次快速单击时复选框无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!