在不少狀況下,咱們須要經過樹列表進行數據的展現,如一些有層次關係的數據,經過有層級的展現,可以使用戶更加直觀查看和管理相關的數據。在通常Winform開發的狀況下,可使用微軟的TreeView控件,也可使用DevExpress的TreeList控件進行數據的展現,本篇隨筆主要介紹基於DevExpress的TreeList控件使用以及使用SearchControl對節點進行查詢的操做。node
在不少狀況下,咱們也傾向於使用TreeView控件做爲數據的展現,相對於TreeList控件,這種控件的處理,須要本身管理樹節點的層次關係,不過使用也比較簡單,呈現的效果二者都差異不大。框架
如在我開發框架中,在字典管理模塊裏面,就是採用這個控件進行數據的展現的,總體效果也還不錯。函數
在樹形列表裏面,咱們獲取數據後,統一根據層級的關係構建樹節點便可,以下代碼所示。this
/// <summary> /// 初始化樹信息 /// </summary> private void InitTreeView() { this.treeView1.Nodes.Clear(); this.treeView1.BeginUpdate(); List<DictTypeNodeInfo> typeNodeList = BLLFactory<DictType>.Instance.GetTree(); foreach (DictTypeNodeInfo info in typeNodeList) { AddTree(null, info); } this.treeView1.EndUpdate(); this.treeView1.ExpandAll(); } /// <summary> /// 根據節點數據,遞歸構建該層級如下的樹節點 /// </summary> /// <param name="pNode">父樹節點</param> /// <param name="info">字典類型數據</param> private void AddTree(TreeNode pNode, DictTypeNodeInfo info) { TreeNode node = null; if (info.PID == "-1") { node = new TreeNode(info.Name, 0, 0); node.Tag = info.ID; this.treeView1.Nodes.Add(node); } else { node = new TreeNode(info.Name, 1, 1); node.Tag = info.ID; pNode.Nodes.Add(node); } foreach (DictTypeNodeInfo subInfo in info.Children) { AddTree(node, subInfo); } }
還有咱們在鼠標選擇某個節點的時候,觸發AfterSelect事件,這樣咱們就能夠處理鼠標節點的事件了spa
/// <summary> /// 單擊節點事件處理 /// </summary> private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { if (e.Node.Tag != null) { this.lblDictType.Text = e.Node.Text; this.lblDictType.Tag = e.Node.Tag; BindData(); } }
以上就是使用TreeView控件來處理數據的展現,從上面代碼能夠看到,總體的內容,主要是經過遞歸的關係來構建TreeNode的處理,可是使用的代碼也不算複雜,所以大多數能夠採用這種方式來自定義樹形節點的展現。code
而使用DevExpress的TeeList控件,能夠經過KeyFieldName和ParentFieldName指定他們的層級關係,使用就更加簡單化,提供的數據源會自動進行層次的關係處理,很是方便。orm
咱們先來看看經過DevExpress的TreeList控件展現的字典類型和字典數據的界面效果。對象
這裏面的效果是如何經過代碼實現的呢?blog
首先咱們使用代碼獲取字典類型數據並進行樹列表控件的初始化操做,以下所示。遞歸
//添加顯示列 this.tree.Columns.Add(new TreeListColumn{ FieldName= "Name", Caption= "字典類型名稱", Width=160, VisibleIndex =0}); //設置樹控件的層次關係及屬性 tree.KeyFieldName = "ID"; tree.ParentFieldName = "PID"; this.tree.OptionsBehavior.Editable = false; this.tree.OptionsView.EnableAppearanceOddRow = true; this.tree.OptionsView.EnableAppearanceEvenRow = true;
上面的代碼咱們還能夠經過擴展函數對樹列表的處理進行封裝,已達到簡化代碼的目的,以下是處理後的實現代碼:
//控件擴展函數封裝處理 this.tree.CreateColumn("Name", "字典類型名稱", 160, true); this.tree.InitTree("ID", "PID", "-1", false, false);
經過添加TreeListColumn對象給TreeList控件就能夠實現字段列的顯示了,同時指定數據源裏面的KeyFieldName和ParentFieldName來設定層級關係便可,很是簡單。
而綁定數據源,則能夠經過一個函數進行處理,以下所示。
/// <summary> /// 綁定樹的數據源 /// </summary> private void BindTree() { this.tree.DataSource = BLLFactory<DictType>.Instance.GetAll(); this.tree.ExpandAll(); }
從上面代碼咱們能夠看到,咱們返回的數據源,不須要在實體類對象層級具備上下級的關係,如經過TreeView實現的時候,咱們使用了DictTypeNodeInfo 對象是具備上下層級關係的。
這裏只須要使用普通的DictTypeInfo 對象集合便可,經過KeyFieldName和ParentFieldName來設定層級關係便可。
爲了指定樹形節點的圖標,咱們能夠經過代碼進行自定義圖標的處理,以下代碼所示,這樣每一個層級的圖標都不同,自動實現獲取設置的處理。
//設置樹的圖標集合及逐級圖標 this.tree.SelectImageList = this.imageCollection1; this.tree.CustomDrawNodeImages += (object sender, CustomDrawNodeImagesEventArgs e)=> { int maxCount = this.imageCollection1.Images.Count; var index = e.Node.Level < maxCount ? e.Node.Level : 0; e.SelectImageIndex = index; };
實現樹節點選中的事件處理,則須要實現FocusedNodeChanged事件便可。
//初始化樹節點選擇事件 this.tree.FocusedNodeChanged += delegate(object sender, FocusedNodeChangedEventArgs e) { this.FocusedNodeChanged(); }; } private void FocusedNodeChanged() { if (this.tree.FocusedNode != null) { var PID = string.Concat(this.tree.FocusedNode.GetValue("ID")); treeConditionSql = string.Format("DictType_ID = '{0}'", PID); } else { treeConditionSql = ""; } BindData(); }
最後初始化樹列表的代碼以下所示。
private void InitTree() { this.tree.Columns.Clear(); //控件擴展函數封裝處理 this.tree.CreateColumn("Name", "字典類型名稱", 160, true); this.tree.InitTree("ID", "PID", "-1", false, false); //設置樹的圖標集合及逐級圖標 this.tree.SelectImageList = this.imageCollection1; this.tree.CustomDrawNodeImages += (object sender, CustomDrawNodeImagesEventArgs e)=> { int maxCount = this.imageCollection1.Images.Count; var index = e.Node.Level < maxCount ? e.Node.Level : 0; e.SelectImageIndex = index; }; }
上面的處理就是樹列表的通常性展現,若是須要在樹節點上面增長一個查詢過濾的操做,那麼可使用SearchControl控件進行過濾處理,只須要設置SearchControl控件的Client屬性,以及實現樹控件的FilterNode事件便可。
/// <summary> /// 實現樹節點的過濾查詢 /// </summary> private void InitSearchControl() { this.searchControl1.Client = this.tree; this.tree.FilterNode += (object sender, DevExpress.XtraTreeList.FilterNodeEventArgs e) => { if (tree.DataSource == null) return; string nodeText = e.Node.GetDisplayText("Name");//參數填寫FieldName if (string.IsNullOrWhiteSpace(nodeText)) return; bool isExist = nodeText.IndexOf(searchControl1.Text, StringComparison.OrdinalIgnoreCase) >= 0; if (isExist) { var node = e.Node.ParentNode; while (node != null) { if (!node.Visible) { node.Visible = true; node = node.ParentNode; } else break; } } e.Node.Visible = isExist; e.Handled = true; }; }
實現效果以下所示, 對於符合記錄的查詢,那麼會有高亮的顏色進行重點標註。