一起谈.NET技术,关于Winform下,获取Treeview中CheckBox选中项的技巧

背景

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

再好一点:

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

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

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

新的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;

新的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

点击获取

时间: 2024-11-02 23:38:56

一起谈.NET技术,关于Winform下,获取Treeview中CheckBox选中项的技巧的相关文章

treeview-跨进程获取 Treeview的Checkbox

问题描述 跨进程获取 Treeview的Checkbox 我已经用读内存的方法实现遍历Treeview获取到文本并点击了,但是要获取到是否有勾选,一直失败,求教具体方法 我是填充结构体,发送?TVM_GETITEMA消息的 解决方案 如何获取别的进程的TreeView控件的内容如何获取别的进程的TreeView控件的内容获取其它进程中TreeView控件的内容 解决方案二: TVM_GETITEMSTATE 用这个消息 https://msdn.microsoft.com/en-us/libra

index-如何获取RadioGroup中被选中的RadioButton的下标?

问题描述 如何获取RadioGroup中被选中的RadioButton的下标? RadioGroup中有个getChildAt(int index)方法,但好像没有获取index的方法,,有谁知道怎么获取吗 解决方案 group.indexOfChild(group.findViewById(checkedId)) 就可以得到index 解决方案二: 你对应的radiobutton不都有自己的ID么....用自己的ID去判断啊 解决方案三: 这个肯定是没有的吧!你点击radiobutton,你通

js获取TreeView控件选中节点的Text和Value值的方法_javascript技巧

在实际项目中,遇到一个问题,首先弹出一个新窗口,新窗口中放了一个TreeView控件,TreeView控件的数据绑定在我的上一篇随笔(TreeView绑定XML数据源C#代码示例)中有讲到,现在要解决的是,如何单击TreeView中一个节点,返回Text和Value到父页面并关闭该新窗口. 首先,在后台代码中为TreeView添加属性onclick以支持TreeView的客户端事件,代码如下: 复制代码 代码如下: if (!IsPostBack) { TreeView1.Attributes.

Linux 下获取LAN中指定IP的网卡的MAC(物理地址)

// all.h// 2005/06/20,a.m. wenxy #ifndef _ALL_H#define _ALL_H #include <memory.h>#include <stdio.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <net/if.h>#include

一起谈.NET技术,ASP.NET MVC 2中使用jQuery UI控件详解

问:我想给我的ASP.NET MVC输入表单添加一个日期选择控件,但模型-视图-控制器(MVC)并没有提供这样的辅助方法,我该如何添加控件? 答:和ASP.NET Web表单不一样,MVC架构没有提供可以在设计面板中拖放的有状态的服务端控件,相反,MVC鼓励使用简单的HTML布局元素和基于数据的标签作为页面布局的要素,功能和最终的布局用客户端JavaScript和CSS样式表控制. MVC提供了一套基于HtmlHelper的扩展方法渲染大部分HTML标签,对于更复杂的功能,你需要自己编写HTML

jQuery中获取checkbox选中项等操作及注意事项_jquery

1. 获取checkbox的选中项 2. checkbox选项的全选 反选操作 用于测试的checkbox代码段: 复制代码 代码如下: <div>            <input type="checkbox" name="abc" value="一年级" id="in1" checked="checked" /><label for="in1">

用javascript获取textarea中的光标位置_javascript技巧

对于写javascript写网页编辑器的人来说,获取textarea中的光标位置是一个非常重要的问题,而往往很多人在这个地方不知所措,找不到好的办法.昨天我在网上找到了一段javascript代码,本来不想把原版放在这里的,就是因为太精彩了,怕我给改坏了,所以还是原版放在这里吧. var start=0;     var end=0;     function add(){                var textBox = document.getElementById("ta"

JavaScript实现获取dom中class的方法_javascript技巧

本文实例讲述了JavaScript实现获取dom中class的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script> function getClass(node,classname) { if(node.getEle

一起谈.NET技术,.Net下的分布式缓存--从Discuz!NT的缓存设计谈起

最近拜读了代振军同学写的关于Discuz!NT的缓存设计的一篇文章<Discuz!NT 缓存设计简析 [原创]>,颇有些想法,姑且写在这里让大家拍砖吧. 缓存真是个好东西,在大型的系统中可以有效地提升系统的速度,此乃废话就不多说了,在.Net 平台下面我把缓存从功用大致分为两类,数据对象缓存和页面输出缓存. 对于数据缓存来讲是由System.Web.Caching.Cache这个类来实现,可以从上下文对象Context.Cache 来获取这个对象的引用.而页面/控件输出缓存则是由.Net环境在