您的位置:首页 > 编程语言 > C#

C#递归遍历树节点并且存储

2016-03-02 10:40 423 查看
前面介绍了TreeView控件生成树,TreeView控件在C#开发中用处很广泛,这里就把我再实际使用的过程中用到的方法总结一下。

1.点击TreeView某一节点,将该节点所有子节点遍历存储。

比如我们想知道父节点下的所有子节点。

我们首先定义一个List<string> 来存储节点

List<string> m_SubNode = new List<string>();
递归遍历节点并且存储子节点

private void RecursionSaveNode(TreeNode tn)
{
foreach (TreeNode tnSub in tn.Nodes)
{
m_SubNode.Add(tnSub.Text); //注意这个位置加上Text,如果写成tnSub.ToString(),那存储的就不是名字了,而是"TreeNode:名字",多了一个TreeNode:字符
RecursionSaveNode(tnSub);
}
}
实际调用过程中

m_SubNode.Clear();
m_SubNode.Add(treeView.SelectedNode.Text); //这句话把点击的父节点也存储了,如果不需要查看父节点,把这句话注释即可。
RecursionSaveNode(treeView.SelectedNode);
2.存储指定的节点,如果在TreeView中加了复选框,来查看TreeView节点是否勾选的状态。

如果父节点勾选,那么所有的子节点都要勾选,如果父节点取消勾选,那么所有子节点都要取消勾选,子节点的勾选一般不会影响父节点,但是如果所有的子节点都取消勾选,那么父节点才取消勾选,如果有一个子节点勾选了,那么父节点也要勾选。

(1)父节点与子节点的逻辑判断

设置子节点的状态。设置子节点的状态很简单,只用把子节点的状态设成跟父节点一样就行了,递归遍历设置所有的子节点即可。

private void setchild(TreeNode node)
{
foreach (TreeNode child in node.Nodes)
{
child.Checked = node.Checked; //子节点状态与父节点一样
setchild(child);
}
}
设置父节点的状态

设置父节点的状态稍微麻烦一些,首先需要判断父节点是否存在,如果不存在则返回,如果存在再进行判断,如果父节点所有的子节点都取消勾选,则父节点取消勾选,如果有一个子节点勾选,则父节点勾选

private void setparent(TreeNode node)
{
if (node.Parent != null)
{
if (node.Checked)
{
node.Parent.Checked = node.Checked;
return;
}
else
{   //判断兄弟节点对父节点的影响
//全部不选则不选,否则勾选
foreach (TreeNode brother in node.Parent.Nodes) //兄弟节点就是父节点的子节点
{
if (brother.Checked == false)
continue;
else
return;
}
node.Parent.Checked = false;
}
}
}
实际调用,实际调用的过程中父子节点的判断写在treeView_AfterCheck事件里面,有一点需要注意,如果是在TreeView加载的过程中就勾选了树节点,那么TreeView初始化时就会触发这个事件,这里就需要屏蔽窗口加载时触发这个事件。

private void treeView_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Action!=TreeViewAction.Unknown) //屏蔽TreeView加载时调用这个事件,只有手动点击TreeView才能触发下面的代码
{
setchild(e.Node);
setparent(e.Node);
}
}
这里也许有人会问,我要一开始就要把所有的子节点都打上勾,那该怎么办?这里我是单独写了一个函数,初始化勾选所有节点,如果用treeView_AfterCheck初始化,会显得挺乱,我把初始化与勾选判断分开来。

private void InitTreeView(TreeNode tn)
{
foreach (TreeNode tnSub in tn.Nodes)
{
tnSub.Checked = true;
InitTreeView(tnSub);

}
}
实际调用的过程中,把第一个节点初始化,调用该函数即可。

treeView.Nodes[0].Checked = true;
InitTreeView(treeView1.Nodes[0]);
(2)存储未选中(选中)的节点,判断未选中(选中)的节点

判断未选中的节点并且存储只用在1中的例子加个判断即可

private void RecursionSaveUnCheckNode(TreeNode tn)
{
foreach (TreeNode tnSub in tn.Nodes)
{
if (tnSub.Checked == false)
{
m_SubUncheckedNode.Add(tnSub.Text);
RecursionSaveUnCheckNode(tnSub);
}

}
}


private void RecursionSaveCheckNode(TreeNode tn)
{
foreach (TreeNode tnSub in tn.Nodes)
{
if (tnSub.Checked == true)
{
m_SubCheckedNode.Add(tnSub.Text);
RecursionSaveCheckNode(tnSub);
}
}
}

实际调用的过程中

m_SubUnCheckedNode.Clear();
RecursionSaveUnCheckNode(treeView.SelectedNode);

m_SubCheckedNode.Clear();
RecursionSaveCheckNode(treeView.SelectedNode);


3.节点的访问

TreeView的节点可以通过数组来进行访问,例如我要访问根节点,则可以这么写treeView.Nodes[0],或者访问根节点下的第三的节点,treeView.Nodes[0].Nodes[2]

节点XXX.Nodes代表节点XXX的子节点

某一节点的父节点 treeView.Nodes[XXX].Parent
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: