Создать список родителей-детей (рекурсивные отношения) из набора данных

Я пытаюсь создать список (HTML) с рекурсивными отношениями. Данные находятся в наборе данных, но могут быть преобразованы в таблицу данных, если это проще.

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

Вот данные:

__ID__ | __NAME__  | __PARENT__     | __LEVEL__ 
1      | Patrick   |                | 1           
2      | Mark      |                | 1
3      | Scott     | 2              | 2
4      | Jason     |                | 1
5      | Julian    |                | 1
6      | John      | 6              | 2
7      | Steve     |                | 1
8      | George    | 1              | 2
9      | Robert    | 1              | 2 
10     | Rodney    | 8              | 3

Здесь вывод, который я хочу произвести

- Patrick [1]
  - George [8]
    - Rodney [10]
  - Robert [9]

- Mark [2]
  - Scott [3]

- Julian [5]
  - John [6]

- Jason [4]

- Steve [7]

person Mark Marina    schedule 25.07.2013    source источник


Ответы (2)


Самый простой способ сделать это — написать рекурсивный метод. То, как он работает, будет зависеть от того, хотите ли вы, чтобы метод возвращал весь древовидный список или выводил данные по мере их чтения. Если вы хотите выводить данные по мере их чтения, ваш код может выглядеть примерно так:

Private Sub OutputTree(data As DataTable, parentId As String, indentationLevel As Integer)
    For Each row As DataRow In GetChildRows(parentId)
        OutputRow(row, indentationLevel)
        OutputTree(data, row("ID").ToString(), indentationLevel + 1)
    Next
End Sub

В приведенном выше коде предполагается, что вы также реализуете метод с именем GetChildRows, который возвращает список всех строк, содержащих заданный родительский идентификатор. Также предполагается, что у вас есть метод с именем OutputRow, который выводит данную строку с заданным уровнем отступа.

Затем вы можете вызвать метод следующим образом:

OutputTree(myDataTable, nothing, 0)

Если вы хотите построить и вернуть древовидную структуру, что, возможно, является лучшим подходом, ваш код может выглядеть примерно так:

Private Function BuildTreeNodes(data As DataTable, parentId As String) As List(Of MyTreeNode)
    Dim nodes As List(OfNew MyTreeNode)()
    For Each row As DataRow In GetChildRows(parentId)
        Dim node As New TreeNode()
        node.Row = row
        node.Children = BuildTreeNodes(data, row("ID").ToString())
        nodes.Add(node)
    Next
    Return node
End Sub

Приведенный выше код предполагает, что вы определили класс MyTreeNode, который будет выглядеть примерно так:

Public Class MyTreeNode
    Public Property Row As DataRow
    Public Property Children As List(Of MyTreeNode)
End Class

Затем вы можете вызвать метод следующим образом:

Dim rootLevelNodes As List(Of MyTreeNode) = BuildTreeNodes(myDataTable, Nothing)
person Steven Doggart    schedule 25.07.2013
comment
Спасибо, Стивен. Сначала я планировал использовать TreeView, но вскоре понял, насколько ограничены элементы управления TreeView. Я не хочу, чтобы список был в таблице, а был заключен в определенные теги HTML (‹ul›, ‹li›). Вот почему я подумал, что использование вложенных повторителей даст мне больше гибкости при выводе списка. - person Mark Marina; 25.07.2013
comment
Я смущен вашим комментарием. Вы хотите сказать, что мои примеры у вас почему-то не сработают, или вы просто предоставили дополнительную информацию? - person Steven Doggart; 25.07.2013
comment
Я упоминал, что элемент управления TreeView (структура дерева) не будет работать в моем случае. Я хочу вывести каждый элемент списка в HTML-теги ‹li› ‹/li› (вложенный список HTML), а элемент управления TreeView не позволит мне этого сделать. Вот почему я подумал, что единственным другим вариантом было использование вложенных повторителей. - person Mark Marina; 25.07.2013
comment
У вас ложное впечатление, что в моих примерах используется элемент управления TreeView? - person Steven Doggart; 25.07.2013

Это будет работать, если ваш __PARENT__ родительского элемента равен нулю.

private void TopItems(DataTable Data)
{
    DataView view = new DataView(Data);
    view.RowFilter = "itemParent IS NULL";

    foreach (DataRowView row in view)
    {
        response.write("parent text: " + row["text"].ToString() + 
                 "parent id: " + row["id"].ToString();
        AddChildMenuItems(Data);
    }
}


//This code is used to recursively add child items by filtering by ParentID
private void AddChildtems(DataTable Data)
{
    DataView view = new DataView(Data);
    view.RowFilter = "itemParent=" + parentMenuItem.Value;
    foreach (DataRowView row in view)
    {
        response.write("child text: " + row["text"].ToString() + 
                 "child id: " + row["id"].ToString();
        AddChildtems(Data);
    }
}
person YaakovHatam    schedule 25.07.2013
comment
Спасибо, Коби. Единственный способ идентифицировать родителя (родителя) — это уровень, который должен быть равен 1. Нулевое значение не гарантируется. Пытаюсь вывести список в HTML (в коде разметки). - person Mark Marina; 25.07.2013
comment
вы можете использовать stringBuilder вместо response.write, чтобы написать свой html. а также может редактировать view.RowFilter = itemParent IS NULL; к вашему фильтру. - person YaakovHatam; 25.07.2013