TreeView، LinQ-To-SQL العودية
-
09-09-2019 - |
سؤال
لدي Ienumerable (من الموظف) مع علاقة ParentID / ChildID مع نفسها يمكنني وجود DataBind إلى TreeView وتظليل التسلسل الهرمي تماما. ومع ذلك، أريد أن أكون قادرا على حلقة يدويا من خلال جميع السجلات وإنشاء جميع العقد برمجيا حتى أتمكن من تغيير السمات لكل عقدة بناء على بيانات العنصر المعطى / لا شيء.
هل هناك برنامج تعليمي يشرح كيفية القيام بذلك؟ لقد رأيت الكثير من استخدام مجموعات البيانات و DataTables ولكن لا شيء يظهر كيفية القيام بذلك في LinQ إلى SQL (iEnumerable)
تحديث:
إليك كيف اعتدت أن أفعل ذلك مع DataSet - لا أستطيع أن أجد كيفية القيام بنفس الشيء مع ienumerable.
Private Sub GenerateTreeView()
Dim ds As New DataSet()
Dim tasktree As New Task(_taskID)
Dim dt As DataTable = tasktree.GetTaskTree()
ds.Tables.Add(dt)
ds.Relations.Add("NodeRelation", dt.Columns("TaskID"), dt.Columns("ParentID"))
Dim dbRow As DataRow
For Each dbRow In dt.Rows
If dbRow("TaskID") = _taskID Then
Dim node As RadTreeNode = CreateNode(dbRow("Subject").ToString(), False, dbRow("TaskID").ToString())
RadTree1.Nodes.Add(node)
RecursivelyPopulate(dbRow, node)
End If
Next dbRow
End Sub
Private Sub RecursivelyPopulate(ByVal dbRow As DataRow, ByVal node As RadTreeNode)
Dim childRow As DataRow
Dim StrikeThrough As String = ""
Dim ExpandNode As Boolean = True
For Each childRow In dbRow.GetChildRows("NodeRelation")
Select Case childRow("StatusTypeID")
Case 2
StrikeThrough = "ActiveTask"
Case 3
StrikeThrough = "CompletedTask"
ExpandNode = False
Case 4, 5
StrikeThrough = "ClosedTask"
ExpandNode = False
Case Else
StrikeThrough = "InactiveTask"
ExpandNode = False
End Select
Dim childNode As RadTreeNode = CreateNode("<span class=""" & StrikeThrough & """><a href=""Task.aspx?taskid=" & childRow("TaskID").ToString() & """>" & childRow("Subject").ToString() & "</a></span>", ExpandNode, childRow("TaskID").ToString())
node.Nodes.Add(childNode)
RecursivelyPopulate(childRow, childNode)
ExpandNode = True
Next childRow
End Sub
Private Function CreateNode(ByVal [text] As String, ByVal expanded As Boolean, ByVal id As String) As RadTreeNode
Dim node As New RadTreeNode([text])
node.Expanded = expanded
Return node
End Function
المحلول
إذا كنت بحاجة فقط إلى وسيلة لتعداد الشجرة، فيمكنك تطبيق هذا كمولد، فقد يبدو الأمر غريبا، فمن المحتمل أن تكون أفضل مع أحد المستخدمين المعرفة من المستخدمين ولكنهم في الأساس نفس الشيء.
public interface IGetChildItems<TEntity>
{
IEnumerable<TEntity> GetChildItems();
}
public static IEnumerable<TEntity> Flatten<TEntity>(TEntity root)
where TEntity : IGetChildItems<TEntity>
{
var stack = new Stack<TEntity>();
stack.Push(root);
while (stack.Count > 0)
{
var item = stack.Pop();
foreach (var child in item.GetChildItems())
{
stack.Push(child);
}
yield return item;
}
}
القيد النوع حيث توجد جمال: IgetchildIDEMS هو فقط يدل على أنك بحاجة إلى مجردة كيفية انزلار التسلسل الهرمي. بدون رمز أعلاه لن يترجم.
سيقوم ذلك بتعداد الشجرة في اتساع أول بطريقة، وسوف تسفر عن العنصر الأصل أولا ثم الأطفال، ثم أطفال هؤلاء الأطفال. يمكنك بسهولة تخصيص التعليمات البرمجية أعلاه لتحقيق سلوك مختلف.
يحرر:
تخبر أشياء عودة العائد المحول البرمجي أنه يجب إرجاع قيمة ثم متابعة. العائد هو الكلمة الرئيسية السياق وتم السماح فقط داخل بيان تكراري. مولد هو وسيلة بسيطة لكتابة مصدر بيانات iEnumerable. سيقوم المحول البرمجي ببناء آلة حالة من هذا الرمز وإنشاء فئة مجهولة غير معروفة. يبدو أن الكلمة الأساسية للعائد غير موجودة في vb.net. ولكن لا يزال بإمكانك كتابة فئة تفعل هذا.
Imports System
Imports System.Collections
Imports System.Collections.Generic
Public Class HierarchyEnumerator(Of TEntity As IGetChildItems(Of TEntity))
Implements IEnumerator(Of TEntity), IDisposable, IEnumerator
Public Sub New(ByVal root As TEntity)
Me.stack = New Stack(Of TEntity)
Me.stack.Push(root)
End Sub
Public Sub Dispose()
End Sub
Public Function MoveNext() As Boolean
Do While (Me.stack.Count > 0)
Dim item As TEntity = Me.stack.Pop
Dim child As TEntity
For Each child In item.GetChildItems
Me.stack.Push(child)
Next
Me.current = item
Return True
Loop
Return False
End Function
Public Sub Reset()
Throw New NotSupportedException
End Sub
Public ReadOnly Property Current() As TEntity
Get
Return Me.current
End Get
End Property
Private ReadOnly Property System.Collections.IEnumerator.Current As Object
Get
Return Me.Current
End Get
End Property
Private current As TEntity
Private stack As Stack(Of TEntity)
End Class