DevExpress中TreeList控件的使用方法

1、前言

DevExpress中,树形结构的显示需要用到TreeList控件。但区别于其他的树形控件,TreeList的数据源绑定方式有些特别,它主要利用子节点编号——Id,还有父节点编号——ParentId确定各个树节点的从属关系,下面开始介绍其用法。

2、构造基础树形结构

首先定义一个实体类Area.cs,代码如下所示:

namespace App
{
    public class Area
    {
        /// <summary>
        /// 节点编号
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 父节点编号
        /// </summary>
        public int ParentId { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
    }
}

然后通过TreeList构造一个基础的树形结构,代码如下:

using System.Collections.Generic;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.ExpandAll();
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

3、给节点添加复选框

很多情况下需要选择一个或多个树节点,此时就需要添加复选框,TreeList添加复选框很简单,代码如下:

using System.Collections.Generic;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;  // 显示复选框
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;  // 实现节点选择联动
            treeList1.ExpandAll();
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

4、给节点添加图标

如果希望给节点添加图标,则需要绑定ImageList,下面的代码添加了4张图片,根据Node的层级Level进行匹配:

using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 图片列表
            ImageList imageList = new ImageList();
            imageList.Images.Add(Bitmap.FromFile(Application.StartupPath + "\\icon\\a.png"));
            imageList.Images.Add(Bitmap.FromFile(Application.StartupPath + "\\icon\\b.png"));
            imageList.Images.Add(Bitmap.FromFile(Application.StartupPath + "\\icon\\c.png"));
            imageList.Images.Add(Bitmap.FromFile(Application.StartupPath + "\\icon\\d.png"));

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;  // 显示复选框
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;  // 实现节点选择联动
            treeList1.SelectImageList = imageList;  // 绑定图标
            treeList1.ExpandAll();

            // 设置图标
            SetImage(treeList1.Nodes);
        }

        // 递归设置节点图标
        private void SetImage(TreeListNodes nodes)
        {
            foreach (TreeListNode node in nodes)
            {
                node.ImageIndex = node.Level;
                node.SelectImageIndex = node.Level;
                SetImage(node.Nodes);
            }
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

5、获取点击的节点值

在使用树控件的时候,必不可少的就是点击树节点并获取该节点的值,但TreeList并没有提供类似NodeClick这样的事件,如果想要获取TreeList的节点值,需要使用MouseClickMouseDoubleClick事件,下面代码演示了鼠标左键点击节点并获取节点值的方法:

using DevExpress.XtraEditors;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // MouseClick事件
        private void treeList1_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                TreeList treeList = sender as TreeList;
                TreeListHitInfo hitInfo = treeList.CalcHitInfo(new Point(e.X, e.Y));
                if (hitInfo.HitInfoType == HitInfoType.Cell)
                {
                    TreeListNode node = hitInfo.Node;
                    XtraMessageBox.Show("选择了:" + node.GetDisplayText(0), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
            }
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

6、获取当前被选中的节点

获取被选中的节点只需要根据CheckState判断即可,代码如下:

using DevExpress.XtraEditors;
using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // 获取被选中的节点
        private void btn_Click(object sender, System.EventArgs e)
        {
            List<TreeListNode> nodes = GetSelectedNodes(treeList1.Nodes);
            StringBuilder builder = new StringBuilder("当前被选中的节点为:\r\n");
            foreach (TreeListNode item in nodes)
            {
                builder.AppendLine(item.GetDisplayText(0));
            }
            XtraMessageBox.Show(builder.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
        }

        // 递归获取当前被选中的节点
        private List<TreeListNode> GetSelectedNodes(TreeListNodes nodes)
        {
            List<TreeListNode> list = new List<TreeListNode>();
            foreach (TreeListNode node in nodes)
            {
                if (node.CheckState == CheckState.Checked)
                {
                    list.Add(node);
                }
            }
            foreach (TreeListNode node in nodes)
            {
                list.AddRange(GetSelectedNodes(node.Nodes));
            }
            return list;
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

7、获取某节点的祖先节点

获取祖先节点只需要根据ParentNode判断即可,代码如下:

using DevExpress.XtraEditors;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // MouseClick事件
        private void treeList1_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                TreeList treeList = sender as TreeList;
                TreeListHitInfo hitInfo = treeList.CalcHitInfo(new Point(e.X, e.Y));
                if (hitInfo.HitInfoType == HitInfoType.Cell)
                {
                    TreeListNode node = hitInfo.Node;
                    List<TreeListNode> selectedNodes = GetAncestorNodes(node);
                    StringBuilder builder = new StringBuilder("当前节点为:" + node.GetDisplayText(0) + "\r\n其祖先节点为:\r\n");
                    foreach (TreeListNode item in selectedNodes)
                    {
                        builder.AppendLine(item.GetDisplayText(0));
                    }
                    XtraMessageBox.Show(builder.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
            }
        }

        // 获取某节点的祖先节点
        private List<TreeListNode> GetAncestorNodes(TreeListNode node)
        {
            List<TreeListNode> list = new List<TreeListNode>();
            while (node.ParentNode != null)
            {
                list.Add(node.ParentNode);
                node = node.ParentNode;
            }
            return list;
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

8、获取某节点的子孙节点

获取子孙节点只需要根据HasChildren判断即可,代码如下:

using DevExpress.XtraEditors;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // MouseClick事件
        private void treeList1_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                TreeList treeList = sender as TreeList;
                TreeListHitInfo hitInfo = treeList.CalcHitInfo(new Point(e.X, e.Y));
                if (hitInfo.HitInfoType == HitInfoType.Cell)
                {
                    TreeListNode node = hitInfo.Node;
                    List<TreeListNode> selectedNodes = GetDescendantNodes(node);
                    StringBuilder builder = new StringBuilder("当前节点为:" + node.GetDisplayText(0) + "\r\n其子孙节点为:\r\n");
                    foreach (TreeListNode item in selectedNodes)
                    {
                        builder.AppendLine(item.GetDisplayText(0));
                    }
                    XtraMessageBox.Show(builder.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                }
            }
        }

        // 获取某节点的子孙节点
        private List<TreeListNode> GetDescendantNodes(TreeListNode node)
        {
            List<TreeListNode> list = new List<TreeListNode>();
            if (node.HasChildren)
            {
                foreach (TreeListNode childNode in node.Nodes)
                {
                    list.Add(childNode);
                }
                foreach (TreeListNode childNode in node.Nodes)
                {
                    list.AddRange(GetDescendantNodes(childNode));
                }
            }
            return list;
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

9、显示多列

现在修改一下Area.cs,新增一个行政区划代码字段,代码如下:

namespace App
{
    public class Area
    {
        /// <summary>
        /// 节点编号
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 父节点编号
        /// </summary>
        public int ParentId { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 行政区划代码
        /// </summary>
        public string Code { get; set; }
    }
}

TreeList中新增一列,代码如下:

using System.Collections.Generic;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国", Code = "" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省", Code = "330000" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市", Code = "330100" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市", Code = "330500" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区", Code = "330102000000" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区", Code = "330108000000" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区", Code = "330105000000" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区", Code = "330106000000" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区", Code = "330109000000" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区", Code = "330110000000" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区", Code = "330113000000" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区", Code = "330112000000" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区", Code = "330114000000" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市", Code = "330111000000" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县", Code = "330122000000" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市", Code = "330182000000" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县", Code = "330127000000" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区", Code = "330502000000" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区", Code = "330503000000" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县", Code = "330522000000" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县", Code = "330523000000" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县", Code = "330521000000" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.Columns[1].Caption = "行政区划代码";
            treeList1.OptionsBehavior.Editable = false;
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }
    }
}

运行结果如下图所示:

在这里插入图片描述
如果定义了多个字段,但又不想显示多列,只需要添加如下代码即可:

treeList1.Columns[1].Visible = false;

10、隔行变色

实现隔行变色的代码如下:

using System.Collections.Generic;
using System.Drawing;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国", Code = "" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省", Code = "330000" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市", Code = "330100" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市", Code = "330500" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区", Code = "330102000000" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区", Code = "330108000000" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区", Code = "330105000000" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区", Code = "330106000000" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区", Code = "330109000000" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区", Code = "330110000000" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区", Code = "330113000000" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区", Code = "330112000000" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区", Code = "330114000000" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市", Code = "330111000000" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县", Code = "330122000000" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市", Code = "330182000000" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县", Code = "330127000000" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区", Code = "330502000000" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区", Code = "330503000000" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县", Code = "330522000000" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县", Code = "330523000000" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县", Code = "330521000000" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.Columns[1].Caption = "行政区划代码";
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            // 奇数行
            treeList1.Appearance.OddRow.BackColor = Color.White;
            treeList1.OptionsView.EnableAppearanceOddRow = true;
            // 偶数行
            treeList1.Appearance.EvenRow.BackColor = Color.AliceBlue;
            treeList1.OptionsView.EnableAppearanceEvenRow = true;
            treeList1.ExpandAll();
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

11、新增节点

新增节点需要使用AppendNode方法,该方法有多个重载,下面的代码演示了新增嘉兴市及其下辖区县:

using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国", Code = "" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省", Code = "330000" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市", Code = "330100" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市", Code = "330500" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区", Code = "330102000000" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区", Code = "330108000000" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区", Code = "330105000000" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区", Code = "330106000000" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区", Code = "330109000000" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区", Code = "330110000000" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区", Code = "330113000000" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区", Code = "330112000000" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区", Code = "330114000000" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市", Code = "330111000000" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县", Code = "330122000000" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市", Code = "330182000000" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县", Code = "330127000000" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区", Code = "330502000000" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区", Code = "330503000000" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县", Code = "330522000000" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县", Code = "330523000000" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县", Code = "330521000000" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.Columns[1].Caption = "行政区划代码";
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // 新增节点
        private void btn_Click(object sender, System.EventArgs e)
        {
            TreeListNode parentNode = treeList1.Nodes[0].Nodes[0];

            // 创建新节点
            TreeListNode root = treeList1.AppendNode("", parentNode.Id);
            root.SetValue(0, "嘉兴市");
            root.SetValue(1, "330400");

            // 南湖区
            TreeListNode node_1 = treeList1.AppendNode("", root);
            node_1.SetValue(0, "南湖区");
            node_1.SetValue(1, "330402000000");

            // 秀洲区
            TreeListNode node_2 = treeList1.AppendNode("", root);
            node_2.SetValue(0, "秀洲区");
            node_2.SetValue(1, "330411000000");

            // 嘉善县
            TreeListNode node_3 = treeList1.AppendNode("", root);
            node_3.SetValue(0, "嘉善县");
            node_3.SetValue(1, "330421000000");

            // 海盐县
            TreeListNode node_4 = treeList1.AppendNode("", root);
            node_4.SetValue(0, "海盐县");
            node_4.SetValue(1, "330424000000");

            treeList1.ExpandAll();
        }
    }
}

运行结果如下图所示:

在这里插入图片描述
乍看之下,上面这段代码好像没什么问题,但其实有一个隐藏的bug新增节点后没有考虑更新祖先节点的选中状态。我们再次运行程序,先选中所有节点,然后再点击新增节点按钮,结果如下图所示:

在这里插入图片描述
由于新增的嘉兴市并未被选中,因此理论上它的两个父节点应该改为半选中状态,现对代码做如下修改:

using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;
using System.Windows.Forms;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国", Code = "" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省", Code = "330000" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市", Code = "330100" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市", Code = "330500" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区", Code = "330102000000" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区", Code = "330108000000" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区", Code = "330105000000" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区", Code = "330106000000" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区", Code = "330109000000" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区", Code = "330110000000" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区", Code = "330113000000" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区", Code = "330112000000" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区", Code = "330114000000" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市", Code = "330111000000" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县", Code = "330122000000" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市", Code = "330182000000" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县", Code = "330127000000" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区", Code = "330502000000" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区", Code = "330503000000" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县", Code = "330522000000" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县", Code = "330523000000" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县", Code = "330521000000" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.Columns[1].Caption = "行政区划代码";
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // 新增节点
        private void btn_Click(object sender, System.EventArgs e)
        {
            TreeListNode parentNode = treeList1.Nodes[0].Nodes[0];

            // 创建新节点
            TreeListNode root = treeList1.AppendNode("", parentNode.Id);
            root.SetValue(0, "嘉兴市");
            root.SetValue(1, "330400");

            // 南湖区
            TreeListNode node_1 = treeList1.AppendNode("", root);
            node_1.SetValue(0, "南湖区");
            node_1.SetValue(1, "330402000000");

            // 秀洲区
            TreeListNode node_2 = treeList1.AppendNode("", root);
            node_2.SetValue(0, "秀洲区");
            node_2.SetValue(1, "330411000000");

            // 嘉善县
            TreeListNode node_3 = treeList1.AppendNode("", root);
            node_3.SetValue(0, "嘉善县");
            node_3.SetValue(1, "330421000000");

            // 海盐县
            TreeListNode node_4 = treeList1.AppendNode("", root);
            node_4.SetValue(0, "海盐县");
            node_4.SetValue(1, "330424000000");

            treeList1.ExpandAll();

            // 更新祖先节点状态
            while (root.ParentNode != null)
            {
                if (root.ParentNode.CheckState == CheckState.Checked)
                {
                    root.ParentNode.CheckState = CheckState.Indeterminate;
                }
                root = root.ParentNode;
            }
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

12、删除节点

删除节点只需要调用DeleteNode方法即可,下面代码演示了删除杭州市节点:

using DevExpress.XtraTreeList.Nodes;
using System.Collections.Generic;

namespace App
{
    public partial class MainForm : DevExpress.XtraEditors.XtraForm
    {
        public MainForm()
        {
            InitializeComponent();
            InitializeTreeComponent();
        }

        // 初始化树组件
        private void InitializeTreeComponent()
        {
            List<Area> list = new List<Area>()
            {
                new Area() { Id = 1, ParentId = 1, Name = "中国", Code = "" },
                new Area() { Id = 2, ParentId = 1, Name = "浙江省", Code = "330000" },
                new Area() { Id = 3, ParentId = 2, Name = "杭州市", Code = "330100" },
                new Area() { Id = 4, ParentId = 2, Name = "湖州市", Code = "330500" },
                new Area() { Id = 5, ParentId = 3, Name = "上城区", Code = "330102000000" },
                new Area() { Id = 6, ParentId = 3, Name = "滨江区", Code = "330108000000" },
                new Area() { Id = 7, ParentId = 3, Name = "拱墅区", Code = "330105000000" },
                new Area() { Id = 8, ParentId = 3, Name = "西湖区", Code = "330106000000" },
                new Area() { Id = 9, ParentId = 3, Name = "萧山区", Code = "330109000000" },
                new Area() { Id = 10, ParentId = 3, Name = "余杭区", Code = "330110000000" },
                new Area() { Id = 11, ParentId = 3, Name = "临平区", Code = "330113000000" },
                new Area() { Id = 12, ParentId = 3, Name = "临安区", Code = "330112000000" },
                new Area() { Id = 13, ParentId = 3, Name = "钱塘区", Code = "330114000000" },
                new Area() { Id = 14, ParentId = 3, Name = "富阳市", Code = "330111000000" },
                new Area() { Id = 15, ParentId = 3, Name = "桐庐县", Code = "330122000000" },
                new Area() { Id = 16, ParentId = 3, Name = "建德市", Code = "330182000000" },
                new Area() { Id = 17, ParentId = 3, Name = "淳安县", Code = "330127000000" },
                new Area() { Id = 18, ParentId = 4, Name = "吴兴区", Code = "330502000000" },
                new Area() { Id = 19, ParentId = 4, Name = "南浔区", Code = "330503000000" },
                new Area() { Id = 20, ParentId = 4, Name = "长兴县", Code = "330522000000" },
                new Area() { Id = 21, ParentId = 4, Name = "安吉县", Code = "330523000000" },
                new Area() { Id = 22, ParentId = 4, Name = "德清县", Code = "330521000000" }
            };

            // 绑定TreeList
            treeList1.DataSource = list;
            treeList1.KeyFieldName = "Id";
            treeList1.ParentFieldName = "ParentId";
            treeList1.Columns[0].Caption = "地区";
            treeList1.Columns[1].Caption = "行政区划代码";
            treeList1.RowHeight = 20;
            treeList1.OptionsView.ShowCheckBoxes = true;
            treeList1.OptionsBehavior.AllowRecursiveNodeChecking = true;
            treeList1.ExpandAll();
        }

        // 删除节点
        private void btn_Click(object sender, System.EventArgs e)
        {
            TreeListNode node = GetNodeByName(treeList1.Nodes, "杭州市");
            if (node != null)
            {
                treeList1.DeleteNode(node);
            }
        }

        // 根据名称获取节点
        private TreeListNode GetNodeByName(TreeListNodes nodes, string name)
        {
            TreeListNode result = null;
            foreach (TreeListNode node in nodes)
            {
                if (node.GetDisplayText(0) == name)
                {
                    result = node;
                    break;
                }
                result = GetNodeByName(node.Nodes, name);
            }
            return result;
        }
    }
}

运行结果如下图所示:

在这里插入图片描述

13、结语

本文主要介绍了TreeList控件的一些常规用法,有兴趣的同志可以参考DevExpress自带的例子深入研究。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值