首页 > 解决方案 > 如何将数据表转换为树视图

问题描述

我有一个类似于下面的数据表:

            col1    col2    col3    col4    col5    col6 
name        jack    joe     will    jack    joe     will      
age         12      5       15      12      16      9 
origin      US      It      SA      Jap     Ven     Fr  

我想从这个表中得到一个类似于下面的树视图:

jack
|_ 12
    |_ US
    |_ Jap
joe
|_ 5
|   |_ It
|_ 16
    |_ Ven     
will
|_ 15  
|   |_ SA
|_ 9
    |_ Fr

该表可能具有或多或少的列数和行数。

要构建树视图,我有一个自定义节点类,如下所示:

public class Node : PropertyChangedBase
{
    private ObservableCollection<Node> mChildren;

    // Add all of the properties of a node here. In this example,
    // all we have is a name and whether we are expanded.
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                NotifyOfPropertyChange(() => Name);
            }
        }
    }
    private string _name;

    public bool IsExpanded
    {
        get { return _isExpanded; }
        set
        {
            if (_isExpanded != value)
            {
                _isExpanded = value;
                NotifyOfPropertyChange(() => IsExpanded);
            }
        }
    }
    private bool _isExpanded;

    // Children are required to use this in a TreeView
    public IList<Node> Children { get { return mChildren; } }

    // Parent is optional. Include if you need to climb the tree
    // from code. Not usually necessary.
    public Node Parent { get; private set; }

    public Node(Node parent = null)
    {
        mChildren = new ObservableCollection<Node>();
        IsExpanded = true;
        Parent = parent;
    }

     
}

这就是我向树中添加节点的方式:

mRootNodes = new ObservableCollection<Node>();

// Test data for example purposes
Node root = new Node() { Name = "Root" };
Node a = new Node(root) { Name = "Node A" };
root.Children.Add(a);
Node b = new Node(root) { Name = "Node B" };
root.Children.Add(b);
Node c = new Node(b) { Name = "Node C" };
b.Children.Add(c);
Node d = new Node(b) { Name = "Node D" };
b.Children.Add(d);
Node e = new Node(root) { Name = "Node E" };
root.Children.Add(e);
mRootNodes.Add(root);

为此,我得到以下树:

root
  Node A
  Node B    
    Node C
    Node D
  Node E

我怎样才能在 C# 中做到这一点?

任何评论表示赞赏。

标签: c#datatabletreeviewconverters

解决方案


假如说:

  1. 每列数据代表新的(或现有的)节点

例如:

if jackin row[0]=> col1andcol4指的是同一个节点

12row[1]=>col1col4指的是同一个节点(的Jack

等等...

  1. 数据表中的每一行代表另一个级别的节点......

那么您需要遍历列和行以将数据转换为Node's 列表。

注意:在下面的示例中,我使用的是List<Node>代替ObservableCollection<Node>(),但这应该给你一个想法......

这是一个Node类定义:

class Node
{
    public string Name{get; set;}
    public List<Node> Children {get; set;}
}

注意:Parent由于循环引用,我删除了成员。

用法(LinqPad):

DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("prop", typeof(string)));
dt.Columns.AddRange(Enumerable.Range(1,6).Select(x=>new DataColumn($"col{x}", typeof(string))).ToArray());
dt.Rows.Add(new object[]{"name", "jack", "joe", "will", "jack", "joe", "will"});
dt.Rows.Add(new object[]{"age", "12", "5", "15", "12", "16", "9"});
dt.Rows.Add(new object[]{"origin", "US", "It", "SA", "Jap", "Ven", "Fr"});

List<Node> nodes = new List<Node>();
for(int c=1; c<dt.Columns.Count; c++)
{
    Node parent = null;
    Node current = null;
    for(int r=0; r<dt.Rows.Count; r++)
    {
        DataRow dr = dt.Rows[r];
        string name = Convert.ToString(dr[c]);
        if(parent==null)
        {
            parent = new Node(){Name = name, Children= new List<Node>()};
            current = nodes.Where(x=>x.Name==parent.Name).SingleOrDefault();
            if(current==null)
                nodes.Add(parent);
            else
                parent = current;
        }
        else
        {
            current = new Node(){Name = name, Children= new List<Node>()};
            if(parent.Children.Where(x=>x.Name==current.Name).SingleOrDefault()==null)
                parent.Children.Add(current);
            else
                current = parent.Children.Where(x=>x.Name==current.Name).SingleOrDefault();
            parent = current;
        }
    }
}
nodes.Dump();

在现实世界中,我建议创建助手类......


推荐阅读