zoukankan      html  css  js  c++  java
  • 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");
  • 相关阅读:
    day37 多路复用IO模型之select select,poll,epoll 异步IO 数据库基本概念 配置文件管理
    day36 协程介绍/yield实现协程/补充/gevent模块/网络IO模型介绍/阻塞IO模型/非阻塞IO模型
    day35 GIL介绍 cpython解释器的垃圾回收机制 GIL与自定义互斥锁 多进程vs多线程 线程queue 进程池与线程池
    day34 线程介绍/开启线程的两种方式/进程vs线程/线程对象其他相关属性或方法/互斥锁/死锁现象与递归锁/信号量
    day33 守护进程、互斥锁、进程间通信、生产者消费者模型part1、生产者消费者模型part2、生产者消费者模型part3
    day 32 进程理论/开启子进程的两种方式/僵尸进程与孤儿进程/进程间内存空间隔离/join操作/进程对象其他相关属性或方法
    day31 基于udp协议套接字通信 udp协议通信循环原理分析 udp协议没有粘包问题/基于socketserver模块实现并发的套接字(tcp) 基于socketserver模块实现并发的套接字(udp) 进程的简单介绍 操作系统的功能介绍 操作系统的发展史
    day30 模拟ssh远程执行命令/解决粘包执行问题/粘包终极解决方案/tcp的优化算法以及粘包问题分析
    Unity3D游戏开发之MatchTarget实现角色攀爬效果
    javase学习第九天(抽象类与接口)
  • 原文地址:https://www.cnblogs.com/zeoy/p/3685262.html
Copyright © 2011-2022 走看看