前面介绍了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