как заполнить дерево? - PullRequest
1 голос
/ 06 июля 2010

У меня есть таблица «Категория». Это просто таблица пользователей, где каждый из них идентифицируется с уникальным UserId и имеет соответствующий ParentId (указывающий на UserId их босса). Если это пользователь верхнего уровня, то для ParentId установлено значение 0. Может кто-нибудь помочь мне найти лучший способ заполнения этого списка в виде дерева?

Ответы [ 3 ]

2 голосов
/ 06 июля 2010

Если вы имеете в виду древовидную структуру WinForms, я бы сделал что-то вроде этого (проверка ошибок пропущена):

private void FillTreeView(object sender, EventArgs e)
{
    // create fake datatable
    DataTable dt = new DataTable();
    dt.Columns.Add("UserId",typeof(int));
    dt.Columns.Add("Name",typeof(string));
    dt.Columns.Add("ParentId", typeof(int));


    dt.Rows.Add(new object[] { 3, "Level_1_A", 2 });
    dt.Rows.Add(new object[] { 4, "Level_1_B", 2 });
    dt.Rows.Add(new object[] { 2, "Level_0_A", 0 });
    dt.Rows.Add(new object[] { 5, "Level_2_A", 3 });
    dt.Rows.Add(new object[] { 6, "Level_2_B", 3 });
    dt.Rows.Add(new object[] { 7, "Level_0_B", 0 });
    dt.Rows.Add(new object[] { 8, "Level_1_C", 7 });

    // call recursive function
    AddCurrentChild(0, dt, treeView1.Nodes);
}

private static void AddCurrentChild(int parentId, DataTable dt, TreeNodeCollection nodes)
{
    var rows = dt.Select("ParentId = " + parentId);
    foreach (var row in rows)
    {
        var userId = (int) row["UserId"];
        var name = row["Name"] as string;

        var node = nodes.Add(userId.ToString(), name.ToString());
        node.Tag = row; // if you need to keep a row reference on the node
        AddCurrentChild(userId, dt, node.Nodes);
    }
}
1 голос
/ 06 июля 2010
1 голос
/ 06 июля 2010

Полагаю, вы знаете, как читать данные из базы данных, поэтому я пропускаю эту часть.

Абстрактная версия - вы можете читать сотрудников из любого источника.

Некоторые вспомогательные сущности (вы можете обойтись без них ofc - использовать этот способ проще / приятнее):

/// <summary>The employee structure with explicit conversion to a TreeNode (you may also use implicit conversion, but i prefer explicit).</summary>
public struct Employee
{
    public int Id;
    public string Name;
    public int BossId;

    public static explicit operator TreeNode(Employee e) { return new TreeNode(e.Name); }
}

public static class EmployeesExtension
{
    /// <summary>More abstract and readable way to add an employee.</summary>
    public static void Add(this Dictionary<int, List<Employee>> employees, int id, string name, int bossId)
    {
        if (!employees.ContainsKey(bossId)) employees[bossId] = new List<Employee>();

        employees[bossId].Add(new Employee() { Id = id, Name = name, BossId = bossId });
    }
}

Метод, используемый для заполнения TreeView:

public static void PopulateTreeView(Dictionary<int, List<Employee>> employees, int bossId, TreeNodeCollection nodes)
{
    if (!employees.ContainsKey(bossId)) return;

    foreach (Employee e in employees[bossId])
    {
        TreeNode tn = (TreeNode)e;
        nodes.Add(tn);
        PopulateTreeView(employees, e.Id, tn.Nodes);
    }
}

Как использовать его в своем коде:

Dictionary<int, List<Employee>> employees = new Dictionary<int, List<Employee>>();

/* Here you will do the actual reading from DB */
//             id,        name,      bossId
employees.Add(666, "The Master     ", 0);
employees.Add(123, "The Underling 1", 666);
employees.Add(879, "The Underling 2", 666);
employees.Add(001, "The Slave 1    ", 123);

this.treeView1.BeginUpdate();
PopulateTreeView(employees, 0, this.treeView1.Nodes);
this.treeView1.EndUpdate();

Использование методов BeginUpdate / EndUpdate устранит «мерцание» вашего графического интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...