DevExpress TreeList 节点查找(类Word导航栏标题查找逻辑)

    前段时间写项目文档,发现Word导航栏标题的节点搜索还是蛮有意思的,想着自己也实现一下这样的逻辑。下图就是Word节点搜索时的图。

DevExpress TreeList 节点查找(类Word导航栏标题查找逻辑)_第1张图片

 

    仔细观察搜索时的行为,可以分析需要实现以下功能:

1、节点递归查找

2、颜色标注匹配节点

3、若匹配节点其父节点尚未展开,则需颜色标注该父节点,表示其子项存在匹配项

4、展开节点时,若节点并非是匹配节点,则取消颜色标注

5、收回节点时,若节点含有匹配子节点,则需按颜色标注

    项目中常常用到DevExpress,TreeList中有个CustomDrawNodeCell事件,可以很好控制每个节点显示的颜色。下面就用Winform+Dev控件简单实现这个功能。

    界面没什么好说的,就拖几个控件就好。

DevExpress TreeList 节点查找(类Word导航栏标题查找逻辑)_第2张图片

    TreeList数据源,大家可以根据项目需要绑定,我这里是自己随便生成的。

class Data
    {
        public static DataTable InitData()
        {
            List lists = GenerateData();
            ModelHandler modelHandler = new ModelHandler();
            return modelHandler.FillDataTable(lists);
        }
        public static List GenerateData()
        {
            List lists = new List() { 
                new NodeModel(){ID=101 ,PARENTID=100,NAME="第一类"},
                new NodeModel(){ID=102 ,PARENTID=100,NAME="第二类"},
                new NodeModel(){ID=103 ,PARENTID=100,NAME="第三类"},
                new NodeModel(){ID=104 ,PARENTID=100,NAME="第四类"},
                new NodeModel(){ID=105 ,PARENTID=100,NAME="第五类"},
                new NodeModel(){ID=106 ,PARENTID=100,NAME="第六类"},
                new NodeModel(){ID=107 ,PARENTID=101,NAME="张三"},
                new NodeModel(){ID=108 ,PARENTID=113,NAME="张三"},
                new NodeModel(){ID=109 ,PARENTID=103,NAME="李四"},
                new NodeModel(){ID=110 ,PARENTID=104,NAME="王五"},
                new NodeModel(){ID=111 ,PARENTID=105,NAME="黄四"},
                new NodeModel(){ID=112 ,PARENTID=106,NAME="王六"},
                new NodeModel(){ID=113 ,PARENTID=102,NAME="第二子类"}
            };
            return lists;
        }
    }
 class NodeModel
    {
        public int ID { get; set; }

        public int PARENTID { get; set; }

        public string NAME { get; set; }
    }

    为了实现上述的功能,逻辑应该是这样的,就是先对节点向下查找,对查找到的匹配节点再进行向上查找父节点,将匹配节点与其父节点区别标记,去重后形成一个集合,将这个集合交给绘制事件,绘制时根据属性判断是否需要颜色标注。

    因此需要写一个节点扩展类,至少包含三个属性,如是否是匹配的节点,是否需要颜色标注,节点的id。

    class NodeEx
    {
        private bool _matchNode;
        public bool MatchNode { get { return _matchNode; } }

        public bool DisPlay { set; get; }

        private int _id;
        public int ID { get { return _id; } }

        private string _Name;
        public string NAME { get { return _Name; } }

        public NodeEx(bool matchNode,TreeListNode node)
        {
            _matchNode = matchNode;
            _id = (int)node.GetValue("ID");
            _Name = node.GetValue("NAME").ToString();
        }
    }
    class Compare:IEqualityComparer
    {
        public bool Equals(NodeEx x,NodeEx y)
        {
            return x.ID == y.ID;
        }
        public int GetHashCode(NodeEx obj)
        {
            return obj.ID.GetHashCode();
        }
    }

    继续实现递归查找方法,以及节点展开事件、节点收缩事件、节点绘制事件

 public partial class Form1 : Form
    {
        private List listResult = new List();//查询结果list
        private List listDisplay = new List();//绘制事件list
        private string filterText = "";//搜索文本
        public Form1()
        {
            InitializeComponent();
            InitStyle();
        }
        private void InitStyle()
        {
            treeList1.Tag = "DATA";
            treeList1.KeyFieldName = "ID";
            treeList1.ParentFieldName = "PARENTID";
            treeList1.DataSource = Data.InitData();
        }
        private void simpleButton1_Click(object sender, EventArgs e)
        {
            listResult.Clear();
            listDisplay.Clear();
            filterText = textEdit1.Text;
            if (string.IsNullOrWhiteSpace(filterText))
            {
                treeList1.Refresh();
                return;
            }
            SearchNodes(treeList1.Nodes);
            listDisplay.AddRange(listResult);
            listDisplay = listDisplay.Distinct(new Compare()).ToList();
            treeList1.Refresh();
        }
        private void SearchNodes(TreeListNodes nodes)
        {
            foreach (TreeListNode node in nodes)
            {
                HighLightNodes(node);
                // 如果当前节点下还包括子节点,就调用递归
                if (node.Nodes.Count > 0)
                {
                    SearchNodes(node.Nodes);
                }
            }
        }
        private void HighLightNodes(TreeListNode node)
        {
            string nodeName = node.GetValue("NAME").ToString();
            if (nodeName.Contains(filterText.ToUpper()) || nodeName.Contains(filterText.ToLower()))
            {
                NodeEx nodeEx = new NodeEx(true, node);
                nodeEx.DisPlay = true;
                listResult.Add(nodeEx);
                SearchParentNode(node);
            }
        }
        /// 
        /// 寻找父节点 是否应该以颜色标注
        /// 
        /// 
        private void SearchParentNode(TreeListNode node)
        {
            if (node.ParentNode != null)
            {
                var rs = listResult.Where(x => x.ID == (int)node.ParentNode.GetValue("ID")).FirstOrDefault();
                //如果没有查找到,则加入list 确认是否需要颜色标注
                //如果查找到,则不需做处理
                if (rs == null)
                {
                    NodeEx nodeEx = new NodeEx(false, node.ParentNode);
                    if (node.ParentNode.Expanded)
                    {
                        nodeEx.DisPlay = false;
                    }
                    else
                    {
                        nodeEx.DisPlay = true;
                    }
                    listDisplay.Add(nodeEx);
                    SearchParentNode(node.ParentNode);
                }
            }
        }
        private void treeList1_AfterExpand(object sender, NodeEventArgs e)
        {
            var rs = listDisplay.Where(x => x.ID == (int)e.Node.GetValue("ID")).FirstOrDefault();
            if (rs != null)
            {
                if (!rs.MatchNode)
                {
                    rs.DisPlay = false;
                }
                treeList1.RefreshNode(e.Node);
            }         
        }
        private void treeList1_AfterCollapse(object sender, NodeEventArgs e)
        {
            var rs = listDisplay.Where(x => x.ID == (int)e.Node.GetValue("ID")).FirstOrDefault();
            if (rs != null)
            {
                if (!rs.MatchNode)
                {
                    rs.DisPlay = true;
                }
                treeList1.RefreshNode(e.Node);
            }
        }
        private void treeList1_CustomDrawNodeCell(object sender, DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs e)
        {
            var lists = listDisplay.Where(x => x.DisPlay == true).ToList();
            foreach (var nodeEx in lists)
            {
                if ((int)e.Node.GetValue("ID")==nodeEx.ID)
                {
                    e.Appearance.BackColor = Color.Yellow;
                }
            }
        }
    }

 最后上实现的效果

DevExpress TreeList 节点查找(类Word导航栏标题查找逻辑)_第3张图片

 

你可能感兴趣的:(C#)