wpf数据自动树结构

  在项目中,时常会遇到存在上下级关系的数据。在呈现方面,按照传统方法,不得不组装TreeNode之后添加到TreeView 中,已实现树形数据的显示。如果项目中需要多处使用树,毫无疑问这将存在巨大的代码冗余,会有无数针对不同实体组件TreeNode的代码出现,整体风格糟糕至极。

  在近期的项目中,很多地方拥有这样的上下级关系,如下图所示,可以清楚的看出它们直接的关系

  在数据的查询上,一般对于Oracle不太熟悉的人,可能就会采用 in或者exist关键字来进行筛选, 实际上Oracle有已经有递归查询的语法存在,对于Oracle不太熟悉的看官,可以百度一下。

这里列出了示例:

select t.project_id,t.project_name,t.p_project_id,t.p_project_name,t.category from sys_project_info s start with s.category in (10,11,21) connect by prior s.project_id=s.p_project_id and s.project_name = s.p_project_name;

  

  到这里数据的提取部分就已经完成,剩下的就是树形数据的组建过程,也就是数据的呈现。归根结底还是递归,在这里只是对递归过程进行了封装,可以直接移植到WPF或者Silverlight项目中,代码如下:

  1 using Microsoft.Practices.Prism.ViewModel;
  2 using System;
  3 using System.Collections;
  4 using System.Collections.Generic;
  5 using System.Collections.ObjectModel;
  6 using System.Linq;
  7 using System.Runtime.Serialization;
  8 using System.Text;
  9 
 10 namespace SysManager.Utility
 11 {
 12     public class TreeNode<T> : NotificationObject where T : BaseEntity
 13     {
 14         private T _parentNode;
 15         private T _currentNode;
 16         private bool _isChecked;
 17         private bool _canChecked;
 18 
 19         /// <summary>
 20         /// 父节点
 21         /// </summary>
 22         public dynamic Key { get; set; }
 23 
 24         /// <summary>
 25         /// 子节点
 26         /// </summary>
 27         public ObservableCollection<TreeNode<T>> ChildrenNodes { get; set; }
 28 
 29         /// <summary>
 30         /// 是否允许被选中
 31         /// </summary>
 32         public bool CanChecked
 33         {
 34             get { return _canChecked; }
 35             set
 36             {
 37                 if (_canChecked == value)
 38                     return;
 39                 _canChecked = value;
 40                 RaisePropertyChanged("CanChecked");
 41             }
 42         }
 43 
 44         /// <summary>
 45         /// 是否处于被选中状态
 46         /// </summary>
 47         public bool IsChecked
 48         {
 49             get { return _isChecked; }
 50             set
 51             {
 52                 if (_isChecked == value)
 53                     return;
 54                 _isChecked = value;
 55                 RaisePropertyChanged("IsChecked");
 56             }
 57         }
 58         /// <summary>
 59         /// 当前选中节点
 60         /// </summary>
 61         public T CurrentNode
 62         {
 63             get { return _currentNode; }
 64             set
 65             {
 66                 if (_currentNode == value)
 67                     return;
 68                 _currentNode = value;
 69                 RaisePropertyChanged("CurrentNode");
 70             }
 71         }
 72         /// <summary>
 73         /// 当前节点的父级节点
 74         /// </summary>
 75         public T ParentNode
 76         {
 77             get { return _parentNode; }
 78             set
 79             {
 80                 if (_parentNode == value)
 81                     return;
 82                 _parentNode = value;
 83                 RaisePropertyChanged("ParentNode");
 84             }
 85         }
 86 
 87         public TreeNode()
 88         {
 89             this.CanChecked = true;
 90         }
 91 
 92         static TreeNode<T> staticNode;
 93 
 94         /// <summary>
 95         /// 将数据组织成一个拥有上下级管理的树形结构数据集合
 96         /// </summary>
 97         /// <typeparam name="TKey">主键的数据类型</typeparam>
 98         /// <param name="nodeSource">执行过GroupBy语句的数据源</param>
 99         /// <param name="resultTreeNode">结果数据</param>
100         /// <param name="keyName">子节点标识字段名称</param>
101         /// <param name="parentKeyName">父节点标识字段名称</param>
102         /// <param name="orderByKeys"></param>
103         /// <returns>已生成的树形结构实体</returns>
104         public TreeNode<T> GenerateTreeNodes<TKey>(IEnumerable<IGrouping<TKey, T>> nodeSource, TreeNode<T> resultTreeNode, string keyName, string parentKeyName)
105         {
106             var orderedSource = nodeSource.OrderBy(groupList => groupList.Key);
107             foreach (IGrouping<TKey, T> item in orderedSource)
108             {
109                 var listChildrenNode = new ObservableCollection<TreeNode<T>>();
110                 object propertyParentValue = null;
111 
112                 foreach (var child in item)
113                 {
114                     //get  children id 
115                     object propertyValue = GetCurrentItemPropertyValue(keyName, child);
116                     //get parent id 
117                     if (propertyParentValue == null)
118                         propertyParentValue = GetCurrentItemPropertyValue(parentKeyName, child);
119 
120                     if (propertyValue != propertyParentValue)
121                     {
122                         T parentNodeInstance = null;
123                         if (propertyParentValue != null)
124                         {
125                             var nodeParent = nodeSource.Where(x => x.Key.ToString() == propertyParentValue.ToString()).FirstOrDefault();
126                             if (nodeParent != null)
127                                 parentNodeInstance = nodeParent.FirstOrDefault();
128                         }
129                         var node = new TreeNode<T>() { CurrentNode = child, Key = propertyValue, ChildrenNodes = new ObservableCollection<TreeNode<T>>(), ParentNode = parentNodeInstance };
130                         listChildrenNode.Add(node);
131                     }
132 
133                 }
134 
135                 TreeNode<T> parentNode = null;
136                 foreach (var root in listChildrenNode)
137                 {
138                     staticNode = null;
139                     parentNode = FindParentNode(resultTreeNode, item.Key);
140                     if (parentNode != null)
141                         break;
142                 }
143                 if (parentNode != null)
144                 {
145                     parentNode.ChildrenNodes = listChildrenNode;
146                 }
147                 else
148                     listChildrenNode.ToList().ForEach(childNode => resultTreeNode.ChildrenNodes.Add(childNode));
149 
150             }
151             return resultTreeNode;
152         }
153 
154         /// <summary>
155         /// 将一个拥有上下级关系的Tree转换为列表
156         /// </summary>
157         public IEnumerable TreeNode2LinkedList { get; private set; }
158         /// <summary>
159         /// 将treenode转换为列表
160         /// </summary>
161         /// <typeparam name="T"></typeparam>
162         /// <param name="originalSource"></param>
163         public void TreeNodeToLinkedList(TreeNode<T> originalSource)
164         {
165             if (originalSource != null && originalSource.ChildrenNodes != null)
166             {
167                 if (originalSource.CurrentNode != null)
168                 {
169                     if (TreeNode2LinkedList == null)
170                         TreeNode2LinkedList = new List<T>();
171                     (TreeNode2LinkedList as List<T>).Add(originalSource.CurrentNode);
172                 }
173                 foreach (var item in originalSource.ChildrenNodes)
174                 {
175                     TreeNodeToLinkedList(item);
176                 }
177             }
178         }
179 
180         private static object GetCurrentItemPropertyValue(string keyName, T child)
181         {
182             var property = child.GetType().GetProperties().Where(prop => prop.Name == keyName).FirstOrDefault();
183             object propertyValue = null;
184             if (property != null)
185                 propertyValue = property.GetValue(child, null);
186             return propertyValue;
187         }
188 
189         /// <summary>
190         /// 寻找当前节点的父级节点
191         /// </summary>
192         /// <param name="rootNode">当前节点</param>
193         /// <param name="key">节点的Key</param>
194         /// <returns>父级节点</returns>
195         private TreeNode<T> FindParentNode(TreeNode<T> rootNode, dynamic key)
196         {
197 
198             if (rootNode.ChildrenNodes == null)
199                 return rootNode;
200             foreach (var children in rootNode.ChildrenNodes)
201             {
202                 if (children.Key == key)
203                 {
204                     staticNode = children;
205                     break;
206                 }
207                 else
208                     if (staticNode == null)
209                         FindParentNode(children, key);
210             }
211             if (rootNode.Key != null && (int)rootNode.Key == key)
212                 return rootNode;
213 
214             return staticNode;
215 
216         }
217     }
218 }
View Code

  

//调用方法
var treeNode = new TreeNode<SysProjectInfoEntity>();
                    treeNode.GenerateTreeNodes<decimal?>(result.OfType<SysProjectInfoEntity>().GroupBy(proj => proj.ParentProjectId), treeNode, "ProjectId", "ParentProjectId");
原文地址:https://www.cnblogs.com/zeoy/p/3685262.html