关于Winform下,获取Treeview中CheckBox选中项的“.NET研究”技巧

简介: 背景今天,在做一个指纹管理平台的界面上,遇到了一些问题,因为公司的基础库中没有针对Winform平台的操作,所以在一个部门选择的场景中,关于如何获取部门TreeView中被选中的项目被难住了。所幸还有一个神器叫做搜索引擎,故谷歌一番,发现Asp.net下的这个问题很好解决,但是关于Winform平台下的类似问题,如凤毛麟角啊!当然,今天我也是查了很久,终于发现了两篇不错的文章,帮助我解决了这个问题,不敢独享,结合自己对使用其方法的心得,特意记录下来,并通过一个小例子和大家一起分享。

背景

今天,在做一个指纹管理平台的界面上,遇到了一些问题,因为公司的基础库中没有针对Winform平台的操作,所以在一个部门选择的场景中,关于如何获取部门TreeView中被选中的项目被难住了。所幸还有一个神器叫做搜索引擎,故谷歌一番,发现Asp.net下的这个问题很好解决,但是关于Winform平台下的类似问题,如凤毛麟角啊!

当然,今天我也是查了很久,终于发现了两篇不错的文章,帮助我解决了这个问题,不敢独享,结合自己对使用其方法的心得,特意记录下来,并通过一个小例子和大家一起分享。

问题是这样的

有一个部门列表,多级的(或者说无限极),我们在Winform端列出来(这个很简单)后,需要对其进行部分的选择,然后通过一个按钮,提交选择好的部门,进入下一个业务操作场景,今天我遇到的问题就是,如何获取这个部门TreeView中,各个级别所选取的项目呢?如下图:

问题描述在这里只是用一个例子来说明,所以就简单一点吧,如左图所示,我们的任务就是通过程序获取被选中的部门,将其信息送到下一个业务场景之中,在传统的Asp.net中,Web.UI下的Treeview控件提供了很方便的接口方法,用于获取被选中的项目,但是来到了Winform下,瞬间杯催……

发现不能用Asp.net的思路来做这个事情后,我立马谷歌了一下,发现如下这篇文章,说的很不错,基本上解决了我遇到的问题,原文地址如下:“时空隧道

我总结了一下,原作者的大概思路应该如下:

流程图图1-简单的流程图示意

解决问题:

在页面(窗体)申明两个变量:

  • 第一个是用于存放被选项目的,文中是StringBuilder对象。
  • 第二个是一个Tag标签,按照原文的话就是“我们在TreeView的结点中用Tag来附加了CheckBox是否选中的标识信息”,字符串对象。

用代码来描述就是如下形式:

 
 
string tag = " True " ; // Tag标签
StringBuilder nodesTag; // 容器

接下来,我们就开始去处理AfterCheck事件,让程序能够“记住”我们选择过的项目。无论大家有没有看过那篇文章,其中提到过“树的递归算法”,关于算法,大家可以参考如下这个链接:点击穿越

在了解完算法后,相信大家能离家如下一段的代码了吧:这里就照搬这位博友的code了

遍历方法
 
  
private void TraversNodes(TreeNode parent)
{
TreeNode node
= parent;
if (node != null )
上海徐汇企业网站设计与制作{
if (node.Tag != null && node.Tag.ToString() == tag)
nodesTag.AppendFormat(
" node:{0} has checked\n " , node.Text);

if (node.FirstNode != null ) /// /如果node节点还有子节点则进入遍历
{
TraversNodes(node.FirstNode);
}
if (node.NextNode != null ) /// /如果node节点后面有同级节点则进入遍历
{
TraversNodes(node.NextNode);
}
}
}

AfterCheck事件代码:

treeView1_AfterCheck
 
  
private void treeView1_AfterCheck( object sender, TreeViewEventArgs e)
{
if (e.Action != TreeViewAction.Unknown)
{
TreeNode node
= e.Node;
if (node.Tag == null )
node.Tag
= tag; // 附加结点信息
else
node.Tag
= null ;

CheckAllChildNodes(e.Node, e.Node.Checked);

// 选中父节点
bool bol = true ;
if (e.Node.Parent != null )
{
for ( int i = 0 ; i < e.Node.Parent.Nodes.Count; i ++ )
{
if ( ! e.Node.Parent.Nodes[i].Checked)
bol
= false ;
}
e.Node.Parent.Checked
= bol;

/// /记得如果父节点被选中或取消,记得设置它的tag哦
if (bol)
{
e.Node.Parent.Tag
= tag;
}
else
{
e.Node.Parent.Tag
= null ;
}
}
}
}

这个方法的调用时机应该是什么时候呢?对于我的场景来说,应该是再点击那个业务按钮之后,在之前,我们的AfterCheck事件代码唯一要做的事情就是如下图所示的一个流程:

当我们点击业务按钮之后,为其添加如下代码即可:

调用方法
 
  
private void 上海企业网站设计与制作style="color: #000000;"> button1_Click_1( object sender, EventArgs e)
{
nodesTag
= new StringBuilder();
TreeNode node
= treeView1.TopNode; // 得到TreeView的根结点,注意根结点只有一个
// 每次搜寻到根结点上海企业网站制作an style="color: #008000;">
while (node.PrevNode != null )
node
= node.PrevNode;
TraversNodes(node);
// 遍历根结点
MessageBox.Show(nodesTag.ToString());
}

再好一点:

到这里呢,按理说问题已经被解决完了。我们获取到了选中的部门,但是,按照常规来说,应该“选中节点的时候,如果节点存在子节点,可以选中全部的子节点;如果取消一个节点的选中状态,当前节点同时又存在父节点的话,就取消父节点的选中状态”,怎么办呢?

我觉得自己很懒,“搜”的一下,给大家链上一篇文章,我觉得写的很不错啊,如下:点此穿越

好啦,根据原文的意思,我们结合之前的获取选中状态的代码,修改如下:

新的AfterCheck
 
  
private void treeView1_AfterCheck( object sender, TreeViewEventArgs e)
{
if (e.Ac上海闵行企业网站制作tion != TreeViewAction.Unknown)
{
TreeNode node
= e.Node;
if (node.Tag == null )
node.Tag
= tag; // 附加结点信息
else
node.Tag
= null ;

CheckAllChildNodes(e.Node, e.Node.Checked);

// 选中父节点
bool bol = true ;
if (e.Node.Parent != null )
{
for ( int i = 0 ; i < e.Node.Parent.Nodes.Count; i 上海徐汇企业网站制作 style="color: #000000;">++ )
{
if ( ! e.Node.Parent.Nodes[i].Checked)
bol
= false ;
}
e.Node.Parent.Checked
= bol;

/// /记得如果父节点被选中或取消,记得设置它的tag哦
if (bol)
{
e.Node.Parent.Tag
= tag;
}
else
{
e.Node.Parent.Tag
= null ;
}
}
}
}

新的CheckAllChildNodes方法:

根据博友Flynn2009的提示,应该注意代码需要有修改,如下:

node.Tag = nodeChecked ? (bool)tag : null;

上海闵行企业网站设计与制作mg id="code_img_opened_b5fcd7f3-5e50-4683-86a2-be50888dcd4a" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('b5fcd7f3-5e50-4683-86a2-be50888dcd4a',event)" src="https://yqfile.alicdn.com/img_405b18b4b6584ae338e0f6ecaf736533.gif" alt="" />新的CheckAllChildNodes
private void CheckAllChildNodes(TreeNode treeNode, bool nodeChecked)
{
foreach (TreeNode node in treeNode.Nodes)
{
node.Checked
= nodeChecked;
node.Tag
= tag;////记得在这里为选中的项目设置tag属性
if (node.Nodes.Count > 0)
{
this.CheckAllChildNodes(node, nodeChecked);
}
}
}

结束:

好啦,在这里呢,我们就完成了获取Treeview中CheckBox选中状态的小例子,并且呢,还人性化的设置了一个关于父子选项的效果。文章就到这里为止吧,希望能给大家带来收获。欢迎拍砖!!!

最后附上本文的示例项目代码:Vs2008+.Net 2.0

点击获取

目录
相关文章
|
21天前
|
网络协议 C#
基于.NET WinForm开发的一款硬件及协议通讯工具
基于.NET WinForm开发的一款硬件及协议通讯工具
|
2月前
|
前端开发 Android开发
WinForm 直接运行 Admin.NET
本文介绍了如何将 Admin.NET 以 WinForm 桌面程序模式运行,简化了手动配置 Web 服务的过程,便于演示和作为单机软件使用。通过添加特定 NuGet 包、修改 `Program.cs` 和 `Form1.cs` 文件,并调整项目配置,最终实现了在 WinForm 中嵌入 WebView 组件显示 Admin.NET 界面的效果。
30 0
WinForm 直接运行 Admin.NET
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
|
5月前
分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了
分享一份 .NET Core 简单的自带日志系统配置,平时做一些测试或个人代码研究,用它就可以了
|
7月前
|
机器学习/深度学习 JSON 测试技术
CNN依旧能战:nnU-Net团队新研究揭示医学图像分割的验证误区,设定先进的验证标准与基线模型
在3D医学图像分割领域,尽管出现了多种新架构和方法,但大多未能超越2018年nnU-Net基准。研究发现,许多新方法的优越性未经严格验证,揭示了验证方法的不严谨性。作者通过系统基准测试评估了CNN、Transformer和Mamba等方法,强调了配置和硬件资源的重要性,并更新了nnU-Net基线以适应不同条件。论文呼吁加强科学验证,以确保真实性能提升。通过nnU-Net的变体和新方法的比较,显示经典CNN方法在某些情况下仍优于理论上的先进方法。研究提供了新的标准化基线模型,以促进更严谨的性能评估。
191 0
|
8月前
|
机器学习/深度学习 算法 数据可视化
MATLAB基于深度学习U-net神经网络模型的能谱CT的基物质分解技术研究
MATLAB基于深度学习U-net神经网络模型的能谱CT的基物质分解技术研究
|
编解码 JSON 算法
一个支持.Net 7的WinForm开源UI组件框架
一个支持.Net 7的WinForm开源UI组件框架
188 0
|
机器学习/深度学习 数据采集 存储
【3-D深度学习:肺肿瘤分割】创建和训练 V-Net 神经网络,并从 3D 医学图像中对肺肿瘤进行语义分割研究(Matlab代码实现)
【3-D深度学习:肺肿瘤分割】创建和训练 V-Net 神经网络,并从 3D 医学图像中对肺肿瘤进行语义分割研究(Matlab代码实现)
278 0
|
数据库 C#
C#,.net,winform导入Excel功能以及下载Excel文件到本地,并使用SqlBulkCopy把DataTable类型的数据写入到sqlserver数据库中
C#,.net,winform导入Excel功能以及下载Excel文件到本地,并使用SqlBulkCopy把DataTable类型的数据写入到sqlserver数据库中
53 0