Visual C#2005中的TreeView控件的使用

最近在一个项目中遇到处理树状层次关系的数据,于是就暂时使用了TreeView来实现,我把其中的主要功能提了出来做成了一个Demo程序,在这里和大家分享,希望各位多多指教。下面就是实现的主要功能以及源码下载。
读取XML文件中的树状结构数据,并用TreeView控件呈现
在相同层级中前后/上下移动节点
删除指定值的节点
把TreeView的节点存储到XML文件中

开发环境:Windows XP SP2, Visual Studio 2005 with SP1
XML数据的组织结构

我的XML数据结构如下所示:
<?xml version="1.0" encoding="utf-8"?>
<TestTreeView>
    <TestNode nodeText="Test1" nodeValue="a" />
    <TestNode nodeText="Test2" nodeValue="b">
        <TestNode nodeText="Test3" nodeValue="c">
            <TestNode nodeText="Test4" nodeValue="d" />
            <TestNode nodeText="Test5" nodeValue="e" />
        </TestNode>
        <TestNode nodeText="Test6" nodeValue="f" />
    </TestNode>
    <TestNode nodeText="Test7" nodeValue="c" />
</TestTreeView>


其中"nodeText"为在TreeView中显示的节点文本,"nodeValue"为该节点实际存储的值,而" a,b,c,d,e,f "为预定义的6个测试值
用TreeView控件呈现XML数据


把上述的XML文件的数据呈现到TreeView控件中主要使用了如下的递归处理:

#region 变量

    private bool enabled = false;
        private string strXmlPath = null;
        private XmlDocument xmlDoc = null;

#endregion

#region 方法

    /// <summary>
        /// 根据XML文件加载树节点
    /// </summary>
        /// <param name="xmlPath">要加载的XML文件路径</param>
        private void LoadTreeNodes(string xmlPath)
        {
            this.xmlDoc = new XmlDocument();
            try
            {
                this.xmlDoc.Load(xmlPath);
                XmlNodeList nodes = this.xmlDoc.SelectNodes("TestTreeView/TestNode");
                this.treeMain.BeginUpdate();
                this.treeMain.Nodes.Clear();
                this.ConvertXmlNodeToTreeNode(nodes, this.treeMain.Nodes);
                this.treeMain.EndUpdate();
            }
            catch (Exception ex)
            {
                MessageBox.Show("程序发生错误:" + ex.Message, "异常", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

       private void ConvertXmlNodeToTreeNode(XmlNodeList xmlNodes, TreeNodeCollection treeNodes)
        {
            foreach (XmlNode xmlNode in xmlNodes)
            {
                string nodeText = xmlNode.Attributes["nodeText"].Value;
                string nodeValue = xmlNode.Attributes["nodeValue"].Value;
                TreeNode newTreeNode = new TreeNode(nodeText);
                newTreeNode.Tag = nodeValue;
                if (xmlNode.HasChildNodes)
                {
                    this.ConvertXmlNodeToTreeNode(xmlNode.ChildNodes, newTreeNode.Nodes);
                }
                treeNodes.Add(newTreeNode);
            }
        }

#endregion
 在相同层级中前后/上下移动节点

这里的移动节点没有使用常见的定义一个Temp变量来存储临时数据,然后把要移动的2个数据交换位置。以“上移”为例,先把要移动的节点删除,再在该节点的前一个节点的位置插入该节点,在删除前把该节点存储在一个临时变量中,而“下移”则类似,下面是主要的代码:
       // 在同级中上移当前节点
    private void btnMoveUp_Click(object sender, EventArgs e)
        {
            TreeNode current = this.treeMain.SelectedNode;
            TreeNode temp = null;
            if (current != null)
            {
                temp = current;
                TreeNode prev = current.PrevNode;

                if (current.Parent != null)
                {
                    TreeNode parent = current.Parent;
                    parent.Nodes.Remove(current);
                    parent.Nodes.Insert(prev.Index, temp);
                }
                else
                {
                    this.treeMain.Nodes.Remove(current);
                    this.treeMain.Nodes.Insert(prev.Index, temp);
                }
                this.treeMain.SelectedNode = temp;
            }
        }

       // 在同级中下移当前节点
    private void btnMoveDown_Click(object sender, EventArgs e)
        {
            TreeNode current = this.treeMain.SelectedNode;
            if (current != null)
            {
                TreeNode next = current.NextNode;
                if (next != null)
                {
                    TreeNode temp = next;
                    if (current.Parent != null)
                    {
                        TreeNode parent = current.Parent;
                        parent.Nodes.Remove(next);
                        parent.Nodes.Insert(current.Index, temp);
                    }
                    else
                    {
                        this.treeMain.Nodes.Remove(next);
                        this.treeMain.Nodes.Insert(current.Index, temp);
                    }
                    this.treeMain.SelectedNode = temp;
                    this.treeMain.SelectedNode = current;
                }
            }
        }

 删除指定值的节点

TreeView节点实际存储的值保存在TreeNode.Tag中,选择要删除的值,然后搜索定位所有节点,最后删除这些节点,重点是遍历所有TreeView的节点搜索具有该值的节点,下面是主要代码:
      // 定位指定值的节点,其中listNodesLocated是一个ListBox控件
   // 列出所有定位到的节点的名称
       private void LocateNodeWithValue(TreeNodeCollection nodes, string nodeValue)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Tag.ToString() == nodeValue)
                {
                    this.listNodesLocated.Items.Add(node.Text);
                }

                if (node.Nodes.Count > 0)
                {
                    this.LocateNodeWithValue(node.Nodes, nodeValue);
                }
            }
        }

      // 删除上述方法定位到的节点
        private void DeleteNode(TreeNodeCollection nodes, string valueToDelete)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.Tag.ToString() == valueToDelete)
                {
                    nodes.Remove(node);
                    this.listNodesLocated.Items.Remove(node.Text);
                }
                else if (node.Nodes.Count > 0)
                {
                    this.DeleteNode(node.Nodes, valueToDelete);
                }
            }
        }
保存TreeView的节点到XML文件中

把编辑后的TreeView中的TreeNode类型的节点转换成XmlNode类型节点保存到XML文件中,该XML文件就是最初选择加载的XML文件,在保存之前要先删除XML中TestTreeView根节点下的所有子节点,主要方法如下:

      // 保存主方法
       private void SaveTreeNodes(string filePath)
        {
            if (this.xmlDoc != null)
            {
                XmlNode root = this.xmlDoc.SelectSingleNode("TestTreeView");
              // 删除根节点下的所有原有节点
                root.RemoveAll();

                this.ConvertTreeNodesToXmlNodes(this.treeMain.Nodes, root);
                this.xmlDoc.Save(this.strXmlPath);
                MessageBox.Show("保存成功!", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

     // 把TreeNode转换成对应的XmlNode
       private void ConvertTreeNodesToXmlNodes(TreeNodeCollection treeNodes, XmlNode xmlNode)
        {
            XmlDocument doc = xmlNode.OwnerDocument;
            foreach (TreeNode treeNode in treeNodes)
            {
                XmlNode newElement = null;
                XmlAttribute attrValue = null;

                newElement = doc.CreateNode(XmlNodeType.Element, "TestNode", "");
                // Set "nodeText"
                attrValue = doc.CreateAttribute("nodeText");
                attrValue.Value = treeNode.Text;
                newElement.Attributes.Append(attrValue);
                // Set "nodeValue"
                attrValue = doc.CreateAttribute("nodeValue");
                attrValue.Value = treeNode.Tag.ToString();
                newElement.Attributes.Append(attrValue);
                xmlNode.AppendChild(newElement);
                if (treeNode.Nodes.Count > 0)
                {
                    this.ConvertTreeNodesToXmlNodes(treeNode.Nodes, newElement);
                }
            }
        }


 这个Demo中的有些方法还有待改善,希望大家多给意见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值