使用Blazor创建递归列表结构

人气:810 发布:2022-10-16 标签: c# asp.net-core blazor

问题描述

我正尝试在Blazor中创建一个递归列表<ul>,这样做看起来合乎逻辑,但我得到了一个奇怪的行为,这是我的代码:

表示ul li的Class元素:

public class Element
{
    public string Title { get; set; }
    public Element Parent { get; set; }
    public int Index { get; set; }
}

ULComponent.Razor:

@if (DataItems?.Count() > 0)
{
  <ul>
        @foreach (var element in DataItems)
        {
            var children = DataItems.Where(e => e.Parent == element).OrderBy(e => e.Index);
            <li>
                @element.Title

                @if (children.Count() > 0)
                {
                    <UlComponent DataItems="children" />
                }
            </li>
        }
  </ul>
}

ULComponent.Razor.cs,代码隐藏:

public partial class ULComponent
{
    [Parameter]
    public IEnumerable<Element> DataItems { get; set; }
}

Razor页面代码隐藏:

protected override void OnInitialized()
{
    var root = new Element { Title = "Root", Index = 1 };
    var element1 = new Element { Title = "Element 1", Index = 1, Parent = root };
    var element2 = new Element { Title = "Element 2", Index = 2, Parent = root };
    var element3 = new Element { Title = "Element 3", Index = 3, Parent = root };
    var element11 = new Element { Title = "Element 1.1", Index = 1, Parent = element1 };
    var element12 = new Element { Title = "Element 1.2", Index = 2, Parent = element1 };
    var element121 = new Element { Title = "Element 1.2.1", Index = 1, Parent = element12 };
    var element21 = new Element { Title = "Element 2.1", Index = 1, Parent = element2 };
    var element22 = new Element { Title = "Element 2.2", Index = 2, Parent = element2 };
    var element31 = new Element { Title = "Element 3.1", Index = 1, Parent = element3 };
    Elements = new List<Element> {root, element1, element2, element3, element11,
           element12, element121, element21, element22, element31};
}

剃须刀页面:

@if (Elements != null)
{
    <div class="row">
        <ULComponent DataItems="Elements"/>
    </div>
    
}

向上编码的结果。

Root
    Element 1
    Element 2
    Element 3
Element 1
    Element 1.1
    Element 1.2
Element 2
    Element 2.1
    Element 2.2
Element 3
    Element 3.1
Element 1.1
Element 1.2
    Element 1.2.1
Element 1.2.1
Element 2.1
Element 2.2
Element 3.1

我正在尝试获取此信息:

Root
Element 1
    Element 1.1
    Element 1.2
        Element 1.2.1
Element 2
    Element 2.1
    Element 2.2
Element 3
    Element 3.1

推荐答案

组件可以嵌套在自身内部。只要您有适当的自引用数据,那么将其解包就非常容易。这样做的好处是,如果您后来决定要将动物&物品归类为&q;物品,则只需将其ParentID更改为8,即可完成。

Element.cs

public class Element
{
    public int ID { get; set; }
    public int? ParentID { get; set; }
    public string Name { get; set; }
}

Parent.razor

<CascadingValue Value="Items">
    <ul>
        <RecursiveUI ParentID="null" />
    </ul>
</CascadingValue>
 
@code {
    List<Element> Items;

    protected override void OnInitialized()
    {
        Items = new List<Element>
        {
            new Element { ID=1, Name="Animals", ParentID = null},
            new Element { ID=2, Name="Mammals", ParentID = 1},
            new Element { ID=3, Name="Birds", ParentID = 1},
            new Element { ID=4, Name="Bears", ParentID = 2},
            new Element { ID=5, Name="Beavers", ParentID = 2},
            new Element { ID=6, Name="Eagles", ParentID = 3},
            new Element { ID=7, Name="Parakeets", ParentID = 3},
            new Element { ID=8, Name="Things", ParentID = null},
            new Element { ID=9, Name="Yo-yos", ParentID = 8},
            new Element { ID=10, Name="Computers", ParentID = 8}
        };
    }
}

RecursiveUI.razor

@foreach (var item in Items.Where(i => i.ParentID == ParentID))
{
    <li>@item.Name
        @if (Items.Where(c=>c.ParentID == item.ID).Any())
        {
           <ul>
               <RecursiveUI ParentID="item.ID"/>  @*THIS IS THE MAGIC.*@
           </ul>
        }
    </li>
}

@code {
    [Parameter]
    public int? ParentID { get; set; }

    [CascadingParameter]
    List<Element> Items { get; set; }
}

824