简体   繁体   English

SQL数据的C#树形视图

[英]C# treeview of SQL data

I have a SQL table looking like this: 我有一个看起来像这样的SQL表:

orderID       customerName        orderDate          valueTotal
================================================================
   1             JohnA            01/02/2013            100
   2             AmandaF          01/02/2013            140
   3             JohnA            05/03/2013             58
   4             FredM            05/03/2013            200

And I want to order this information on a treeView by either orderDate or customerName , depending on user settings so that it looks like this if ordered by customerName: 我想通过orderDatecustomerNametreeView上订购此信息,具体取决于用户设置,以便如果由customerName订购则看起来像这样:

JohnA
    01/02/2013
    05/03/2013
AmandaF
    01/02/2013
FredM
     05/03/2013

Or like this if ordered by orderDate: 如果按orderDate订购,则类似这样:

01/02/2013
    JohnA
    AmandaF
05/03/2013
    JohnA
    FredM

What would be the best way to achieve this? 实现这一目标的最佳方法是什么?

EDIT: I'm using windows forms 编辑:我正在使用Windows窗体

If you're using ADO.Net, test this: 如果您使用的是ADO.Net,请进行以下测试:

Dictionary<string, List<string>> groups = new Dictionary<string, List<string>>();

//set these dynamic
string groupingFieldName = "customerName";
string targetFieldName = "orderDate";


SqlDataReader rdr = sqlCmd.ExecuteReader();
while (rdr.Read())
{
    if (!groups.ContainsKey(rdr[groupingFieldName].ToString()))
    {
         groups.Add(rdr[groupingFieldName].ToString(), new List<string>());
    }
    groups[rdr[groupingFieldName].ToString()].Add(rdr[targetFieldName].ToString());
}

//next, iterate the dictionary and populate the treeView
foreach (KeyValuePair<string, List<string>> group in groups)
{
     //add to treeView
}

Please note that this is not tested. 请注意,这未经测试。 You still need to test it. 您仍然需要对其进行测试。

I've ended up creating two functions to perform this in a more dynamic and scalable way. 我最终创建了两个函数来以更动态和可扩展的方式执行此操作。

    public static TreeNodeCollection SqlToTreeNodeHierarchy(this SqlDataReader dataReader, TreeNode parent)
    {
        // create a parent TreeNode if we don't have one, so we can anchor the new TreeNodes to it
        // I think this will work better than a list since we might be given a real parent..
        if (parent == null)
        {
            parent = new TreeNode("topNode");
        }

        while (dataReader.Read())
        {
            //at the beginning of each row, reset the parent
            var parentNode = parent;

            for (var i = 0; i < dataReader.FieldCount; i++)
            {
                // Adds a new TreeNode as a child of parentNode if it doesn't already exist
                // at this level, else it will return the existing TreeNode and save 
                // it onto parentNode. This way, subsequent TreeNodes will always be a child 
                // of this one, until a new row begins and the parent TreeNode is reset.
                parentNode = AddUniqueNode(dataReader[i].ToString(), parentNode);
            }
        }

        return parent.Nodes;
    }

    public static TreeNode AddUniqueNode(string text, TreeNode parentNode)
    {
        // if parentNode is null, create new treeNode and return it
        if (parentNode == null)
        {
            return new TreeNode {Name = text, Text = text};
        }

        // if parentNode is not null, do a find for child nodes at this level containing the key
        // we're after (text and name have the same value) and return the first one it finds
        foreach (var childNode in parentNode.Nodes.Find(text, false))
        {
            return childNode;
        }

        // Node does not yet exist, so just add a new node to the parentNode and return that
        return parentNode.Nodes.Add(text, text);
    }

Then I just need to call the functions as follows: 然后,我只需要调用以下函数:

using (var sqlConn = new SqlConnection(connectionString))
{
    sqlConn.Open();

    const string query = "SELECT orderDate, customerName from MAIN";

    using (var sqlCommand = new SqlCommand(query, sqlConn))
    {
        using (var sqlDataReader = sqlCommand.ExecuteReader())
        {
            var treeNodeCollection = sqlDataReader.SqlToTreeNodeHierarchy(null);

            foreach (TreeNode treeNode in treeNodeCollection)
            {
                nativeTreeView.Nodes.Add(treeNode);
            }
        }
    }
}

This way I can make it scale with as many child nodes as I want and it also gives me the flexibility of loading the child nodes only when on expand by doing another SQL query and passing the parent as the TreeNode that was just expanded. 通过这种方式,我可以根据需要扩展子节点的数量,并且还提供了仅在扩展时才加载子节点的灵活性,方法是执行另一个SQL查询并将父节点传递给刚刚扩展的TreeNode。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM