關于Winform下,獲取Treeview中CheckBox選中項的技巧

作者: Jack Fan  來源: 博客園  發布時間: 2011-03-22 11:54  閱讀: 5477 次  推薦: 0   原文鏈接   [收藏]  
摘要:本文是從WinForm場景中實現了在網站開發中經常使用的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

點擊獲取

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()