博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[总结]关于Winform下,获取Treeview中CheckBox选中项的技巧
阅读量:6479 次
发布时间:2019-06-23

本文共 3640 字,大约阅读时间需要 12 分钟。

背景

今天,在做一个指纹管理平台的界面上,遇到了一些问题,因为公司的基础库中没有针对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了

ContractedBlock.gif
ExpandedBlockStart.gif
遍历方法
 
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事件代码:

ContractedBlock.gif
ExpandedBlockStart.gif
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事件代码唯一要做的事情就是如下图所示的一个流程:

2011031815262317.jpg

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

ContractedBlock.gif
ExpandedBlockStart.gif
调用方法
 
private
void
button1_Click_1(
object
sender, EventArgs e)
{
nodesTag
=
new
StringBuilder();
TreeNode node
=
treeView1.TopNode;
//
得到TreeView的根结点,注意根结点只有一个
//
每次搜寻到根结点
while
(node.PrevNode
!=
null
)
node
=
node.PrevNode;
TraversNodes(node);
//
遍历根结点
MessageBox.Show(nodesTag.ToString());
}

再好一点:

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

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

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

ContractedBlock.gif
ExpandedBlockStart.gif
新的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
;
}
}
}
}

新的CheckAllChildNodes方法:

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

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

ContractedBlock.gif
ExpandedBlockStart.gif
新的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

转载地址:http://gkwuo.baihongyu.com/

你可能感兴趣的文章
Python~迭代
查看>>
linux常用命令-关机、重启
查看>>
css布局 - 九宫格布局的方法汇总(更新中...)
查看>>
ejabberd_local
查看>>
BZOJ5020 [THUWC 2017]在美妙的数学王国中畅游LCT
查看>>
hdu 6030 矩阵快速幂
查看>>
tomcat类加载机制
查看>>
Java基础学习总结(94)——Java线程再学习
查看>>
iOS开发之调用系统设置
查看>>
利用 ACPI\\ACPI0003设备 判断笔记本还是台式机
查看>>
解决wampserver 服务无法启动
查看>>
初次使用 VUX
查看>>
javascript 字符串转数字的简便写法
查看>>
html之div始终停留在屏幕中间部分
查看>>
Spring中jdbcTemplate的用户实例
查看>>
[模板] 快速傅里叶变换/FFT/NTT
查看>>
DecimalFormat 数据格式设置 SimpleDateFormat时间格式的用法介绍 --转载
查看>>
Android 的Margin和Padding属性以及支持的长度单位
查看>>
HDU ACM 1050 Moving Tables
查看>>
Django templates加载css/js/image等静态资源
查看>>