winform中TreeView控件复选框联动时鼠标点击过快导致的显示不正确的问题
今天我在试着做一个C#树形视图(TreeView)控件,要求在每个节点前面添加一个可用于打勾的复选框,并要求复选框有上下级联动的效果。现在在网上能查到挺多满足这类功能的代码,原本我也以为这是一件挺简单的事情,不过实际情况并非如此。
我们建立一个C#窗体应用程序,主窗体取名FormMain,在里面放置一个Dock为Fill的TreeView控件treeTest。注意该控件的CheckBoxes属性要设置为True才能显示复选框。
在FormMain中写入代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace TreeViewCheckTest
{public partial class FormMain : Form{public FormMain(){InitializeComponent();}private void FormMain_Load(object sender, EventArgs e){//生成测试数据TreeNode treeNode11 = new TreeNode("蜉蝣目");treeNode11.Nodes.Add("等蜉科");treeNode11.Nodes.Add("四节蜉科");treeNode11.Nodes.Add("扁蜉科");treeNode11.Nodes.Add("蜉蝣科");treeNode11.Nodes.Add("河花蜉科");TreeNode treeNode12 = new TreeNode("蜚蠊目");treeNode12.Nodes.Add("姬蠊科");treeNode12.Nodes.Add("硕蠊科");treeNode12.Nodes.Add("地鳖科");treeNode12.Nodes.Add("隐尾蠊科");TreeNode treeNode13 = new TreeNode("螳螂目");treeNode13.Nodes.Add("螳科");treeNode13.Nodes.Add("花螳科");treeNode13.Nodes.Add("锥头螳科");treeNode13.Nodes.Add("细足螳科");TreeNode treeNode14 = new TreeNode("其他类型昆虫");TreeNode treeNode1 = new TreeNode("昆虫纲");treeNode1.Nodes.AddRange(new TreeNode[] { treeNode11, treeNode12, treeNode13, treeNode14 });treeTest.Nodes.Add(treeNode1);treeTest.ExpandAll();}/// <summary>/// 关联锁/// </summary>bool needSetRelateCheck = true;/// <summary>/// 树节点前复选框发生变化时触发/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void treeViewEnhanced1_AfterCheck(object sender, TreeViewEventArgs e){if (!needSetRelateCheck){return;}//1、判断当前操作节点勾还是不勾//如果勾,当前节点下所有子节点都要勾上//如果不勾,下面子节点全部不勾TreeNode node = e.Node;if (node.Checked){node.Nodes.OfType<TreeNode>().ToList().ForEach(x => x.Checked = true);}else{node.Nodes.OfType<TreeNode>().ToList().ForEach(x => x.Checked = false);}//2、如果当前节点被勾选,如果当前节点被勾选,则其上溯所有祖先节点都要勾//否则判断当前节点所有兄弟节点是否有勾,有则父节点要勾,没有则父节点不勾needSetRelateCheck = false; //为本方法上锁,确保连带影响不会运行本事件中代码if (node.Checked){while (node.Parent != null){node = node.Parent;node.Checked = true;}}else{while (node.Parent != null){node = node.Parent;bool hasCheckedChild = false;foreach (TreeNode child in node.Nodes){if (child.GetHashCode() == e.Node.GetHashCode()){continue;}if (child.Checked){hasCheckedChild = true;break;}}if (!hasCheckedChild){node.Checked = false;}else{break;}}}needSetRelateCheck = true; //为本方法解锁}}
}
原则上这段代码满足以下功能:
1:勾选一个节点时,该节点的所有子节点都被勾选
2:取消勾选一个节点时,该节点的所有子节点都被取消勾选
3:勾选一个节点时,如果该节点的所有兄弟都被勾选,则该节点的父节点也应被勾选
4:取消勾选一个节点时,如果该节点的所有兄弟节点都未被勾选,则该节点的父节点也应被取消勾选
运行后效果如下:
本来以为这样就好了,结果发生了意想不到的事情:
在我用鼠标点击一个复选框时,如果点击间隔时间过短(达到类似双击的速度),则TreeView的复选框会显示出现无法正确联动的问题。
后来我上网查了一些资料,终于找到了一个大牛给出的原因,参见:
https://social.msdn.microsoft.com/Forums/windows/en-US/9d717ce0-ec6b-4758-a357-6bb55591f956/possible-bug-in-net-treeview-treenode-checked-state-inconsistent?forum=winforms
大牛的答案中说这是一个WindowsVista版本的BUG,不过我现在的32位Win7也会出现此问题。
解决这个问题的方法是将TreeView封装一层,并重写一下WndProc函数:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace TreeViewCheckTest
{/*此种重写此函数,会导致鼠标触发的时候变的缓慢,*/class TreeViewEnhanced : TreeView{protected override void WndProc(ref Message m){if (m.Msg == 0x203) { m.Result = IntPtr.Zero; }else base.WndProc(ref m);}}//改进方法(用此类控件代替将响应变的更快)public class TreeViewEx : TreeView{private const int WM_LBUTTONDBLCLK = 0x0203;private const int WM_RBUTTONDOWN = 0x0204;protected override void WndProc(ref Message m){if (m.Msg == WM_LBUTTONDBLCLK){TreeViewHitTestInfo tvhti = HitTest(new Point((int)m.LParam));if (tvhti != null && tvhti.Location == TreeViewHitTestLocations.StateImage){m.Result = IntPtr.Zero;tvhti.Node.Checked = !tvhti.Node.Checked;return;}}else if (m.Msg == WM_RBUTTONDOWN){TreeViewHitTestInfo tvhti = HitTest(new Point((int)m.LParam));if (tvhti != null)this.SelectedNode = tvhti.Node;}base.WndProc(ref m);}}
实现了TreeViewEnhanced类后,将FormMain中的TreeView控件替换为我们刚刚实现的TreeViewEnhanced就好啦!
转载:https://blog.csdn.net/weixin_34364135/article/details/92548715
转载于:https://my.oschina.net/Tsybius2014/blog/551358
winform中TreeView控件复选框联动时鼠标点击过快导致的显示不正确的问题相关推荐
- C# - 解决TreeView控件复选框联动时鼠标点击过快导致的显示不正确的问题
2019独角兽企业重金招聘Python工程师标准>>> 今天我在试着做一个C#树形视图(TreeView)控件,要求在每个节点前面添加一个可用于打勾的复选框,并要求复选框有上下级联动 ...
- 关于怎么获取Repeater控件复选框选中的那一行的数据
关于怎么获取Repeater控件复选框选中的那一行的数据 1.首先你要有一个repeater控件,并且里面有复选框控件 2.废话不多话,直接上代码 Dim i As Integer'Car是repea ...
- Winform中Treeview控件失去焦点,将选择的节点设置为高亮显示 (2012-07-16 13:47:07)转载▼...
Winform中Treeview控件失去焦点,将选择的节点设置为高亮显示 (2012-07-16 13:47:07)转载▼ 标签: winform treeview drawnode Treeview ...
- 5、Web 窗体的基本控件——复选框控件和复选组控件(CheckBox 和 CheckBoxList)
5.Web 窗体的基本控件--复选框控件和复选组控件(CheckBox 和 CheckBoxList) 复选框控件和复选组控件(CheckBox 和 CheckBoxList) 前端 <%@ P ...
- html5 多选框控件,复选框和单选框都属于控件吗
单选框和复选框的区别是什么? 单选框和复选框的区别是什么? 详细一点-. (1)复选框可以允许你选择多个设置,而单选框则允许你选择一个设置: 这两个选框的区别是一个通过用圆圈表示,一个通过用方框表示. ...
- winform中treeview控件实现部分节点显示checkbox
用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示checkbox哪些不显示,可是winform中的treeview只提供一个Sho ...
- 在 GridView 控件中添加一列复选框51
简介 在前面的教程中 , 我们学习了如何为 GridView 控件添加一列 单选 按钮来选择一个特定的记录.当用户被限制最多只能从网格中选中一项时,一列单选按钮是一个非常恰当的用户界面.然而,有时我们 ...
- 扩展GridView控件(7) - 行的指定复选框选中时改变行的样式
GridView既强大又好用.为了让它更强大.更好用,我们来写一个继承自GridView的控件. [索引页] [×××] 扩展GridView控件(7) - 行的指定复选框选中时改变行的样式 作者:w ...
- asp.NET中 treeview 控件的使用
asp.NET中 treeview 控件的使用 treeview控件实现点击Node,弹出相应WebUserControl画面 所需控件 treeview控件 WebUserControl,web用户 ...
最新文章
- 高效排序算法(希尔排序)
- python中内置函数基本输入输出函数
- 江苏省二级c语言考试软件下载,江苏省二级c语言上机考试例题集1-20
- Android 解决下拉刷新控件和ScrollVIew的滑动冲突问题。
- 从《网管员必读》系列丛书获奖看读者的真正需求——成功原因分析(一)
- 跨界合作成潮流 智能家居竞争升级
- 原创玄幻小说--那时花开--第一章前序
- 符合W3C的网站的开发模型和必要性的探讨(一)
- 蚂蚁金服旗下网商银行招聘了
- 计算机老是跳出usb设备无法识别,如何解决电脑一直弹出USB设备无法识别的问题?...
- java url 收集
- 推荐 7 款国产的在线HTML编辑器
- Error:Internal error: (java.lang.IllegalArgumentException) Argument for
- 思科高级配置(配置标准ACL)
- 月薪20K,北漂程序员的真实生活
- 网易实习第11天--制作第一个ios应用
- 【宝藏】GitHub黑科技的开源项目(有趣高质量)
- 【Redis核心知识 八】Redis集群之Cluster模式及集群搭建
- Quartz查询所有的定时任务
- Latex表格置顶方法