Enterprise-level component library based on Bootstrap and Blazor

star nuget license download repo commit master coverage

Table 树形数据展示

表格支持树形数据的展示

通过设置 IsTree 开启树形表格

Demo
Loading...

通过设置 IndentSize 以控制每一层的缩进宽度。

Demo

本例中更改缩进宽度为 8px

Loading...

实现简单的增、删、改、查功能。

Demo

通过设置 TreeIcon 更改指示小箭头图标

Demo

本例中更改缩进宽度为 8px

Loading...
@inherits BootstrapComponentBase
@page "/tables/tree"

<h3>Table 树形数据展示</h3>

<h4>表格支持树形数据的展示</h4>

<Tips>
    <div>通过 <code>IsTree</code> 参数控制是否为树形数据,通过 <code>HasChildrenColumnName</code> 参数控制当前行是否有子数据,点击子项展开小箭头时,通过 <code>OnTreeExpand</code> 回调委托方法获取子项数据</div>
</Tips>

<DemoBlock Title="树形数据展示" Introduction="通过设置 <code>IsTree</code> 开启树形表格" Name="TreeData">
    <Tips>
        <div>出于性能考虑,默认子项未展开,点击小箭头后,触发 <code>OnTreeExpand</code> 回调委托方法,再此方法中对当前行的子数据进行赋值,<code>Table</code> 组件进行渲染新数据</div>
    </Tips>
    <Table TItem="FooTree" IsBordered="true" IsStriped="true" HeaderStyle="@TableHeaderStyle.Light"
           Items="@TreeItems" IsTree="true" OnTreeExpand="@OnTreeExpand">
        <TableColumns>
            <TableColumn @bind-Field="@context.Name" Width="360" />
            <TableColumn @bind-Field="@context.DateTime" Width="180" />
            <TableColumn @bind-Field="@context.Address" />
            <TableColumn @bind-Field="@context.Count" />
        </TableColumns>
    </Table>
</DemoBlock>

<DemoBlock Title="层次缩进" Introduction="通过设置 <code>IndentSize</code> 以控制每一层的缩进宽度。" Name="Level">
    <Tips>
        <div>默认层次缩进宽度为 <code>16px</code> 通过设置 <code>Indent</code> 更改缩进宽度</div>
    </Tips>
    <p>本例中更改缩进宽度为 <code>8px</code></p>
    <Table TItem="FooTree" IsBordered="true" IsStriped="true" HeaderStyle="@TableHeaderStyle.Light"
           Items="@TreeItems" IsTree="true" OnTreeExpand="@OnTreeExpand" IndentSize="8">
        <TableColumns>
            <TableColumn @bind-Field="@context.Name" Width="360" />
            <TableColumn @bind-Field="@context.DateTime" Width="180" />
            <TableColumn @bind-Field="@context.Address" />
            <TableColumn @bind-Field="@context.Count" />
        </TableColumns>
    </Table>
</DemoBlock>

<DemoBlock Title="具有单表维护功能的树形数据" Introduction="实现简单的增、删、改、查功能。" Name="EditTree">
    <Tips>
        <div>通过在实体的唯一标识字段上定义 <code>[Key]</code> 特性,来保持展开状态</div>
    </Tips>
    <Table TItem="EditFooTree" IsBordered="true" HeaderStyle="@TableHeaderStyle.Light"
           ShowToolbar="true" ShowExtendButtons="true" ShowSkeleton="true" IsStriped="true"
           OnQueryAsync="@OnQueryAsync" OnAddAsync="@OnAddAsync" OnSaveAsync="@OnSaveAsync"
           OnDeleteAsync="@OnDeleteAsync" IsTree="true" OnTreeExpand="@OnTreeExpandQuery">
        <TableColumns>
            <TableColumn @bind-Field="@context.Id" />
            <TableColumn @bind-Field="@context.Name" Width="360" />
            <TableColumn @bind-Field="@context.DateTime" Width="180" />
            <TableColumn @bind-Field="@context.Address" />
            <TableColumn @bind-Field="@context.Count" />
            <TableColumn @bind-Field="@context.ParentId" />
        </TableColumns>
    </Table>
</DemoBlock>

<DemoBlock Title="图标" Introduction="通过设置 <code>TreeIcon</code> 更改指示小箭头图标" Name="Icon">
    <Tips>
        <div>默认层次缩进宽度为 <code>16px</code> 通过设置 <code>Indent</code> 更改缩进宽度</div>
    </Tips>
    <p>本例中更改缩进宽度为 <code>8px</code></p>
    <Table TItem="FooTree" IsBordered="true" IsStriped="true" HeaderStyle="@TableHeaderStyle.Light" TreeIcon="fa fa-chevron-circle-right"
           Items="@TreeItems" IsTree="true" OnTreeExpand="@OnTreeExpand" IndentSize="8">
        <TableColumns>
            <TableColumn @bind-Field="@context.Name" Width="360" />
            <TableColumn @bind-Field="@context.DateTime" Width="180" />
            <TableColumn @bind-Field="@context.Address" />
            <TableColumn @bind-Field="@context.Count" />
        </TableColumns>
    </Table>
</DemoBlock>
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;

namespace BootstrapBlazor.Shared.Samples.Table;

/// <summary>
/// 树形数据演示示例代码
/// </summary>
public partial class TablesTree
{
    [NotNull]
    private List<EditFooTree>? AllItems { get; set; }

    [NotNull]
    private IEnumerable<FooTree>? TreeItems { get; set; }

    [Inject]
    [NotNull]
    private IStringLocalizer<Foo>? Localizer { get; set; }

    private int level = 0;

    /// <summary>
    /// OnInitialized 方法
    /// </summary>
    protected override void OnInitialized()
    {
        base.OnInitialized();

        TreeItems = FooTree.Generate(Localizer);
        AllItems = new List<EditFooTree>();
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 10, 1));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 20, 2));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 30, 11));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 40, 12));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 50, 21));
        AllItems.AddRange(EditFooTree.Generate(Localizer, AllItems, 60, 22));
    }

    private async Task<IEnumerable<FooTree>> OnTreeExpand(FooTree foo)
    {
        await Task.Delay(1000);
        return FooTree.Generate(Localizer, level++ < 2, foo.Id + 10).Select(i =>
        {
            i.Name = Localizer["Foo.Name", $"{foo.Id:d2}{i.Id:d2}"];
            return i;
        });
    }

    private Task<EditFooTree> OnAddAsync() => Task.FromResult(new EditFooTree() { AllItems = AllItems, DateTime = DateTime.Now });

    private Task<bool> OnSaveAsync(EditFooTree item, ItemChangedType changedType)
    {
        if (changedType == ItemChangedType.Add)
        {
            item.Id = AllItems.Max(i => i.Id) + 1;
            AllItems.Add(item);
        }
        else
        {
            var oldItem = AllItems.FirstOrDefault(i => i.Id == item.Id);
            if (oldItem != null)
            {
                oldItem.ParentId = item.ParentId;
                oldItem.Name = item.Name;
                oldItem.DateTime = item.DateTime;
                oldItem.Address = item.Address;
                oldItem.Count = item.Count;
            }
        }
        return Task.FromResult(true);
    }

    private Task<bool> OnDeleteAsync(IEnumerable<EditFooTree> items)
    {
        items.ToList().ForEach(i => AllItems.Remove(i));
        return Task.FromResult(true);
    }

    private Task<QueryData<EditFooTree>> OnQueryAsync(QueryPageOptions _)
    {
        return Task.FromResult(new QueryData<EditFooTree>()
        {
            Items = AllItems.Where(f => f.ParentId == 0)
        });
    }

    private async Task<IEnumerable<EditFooTree>> OnTreeExpandQuery(EditFooTree foo)
    {
        await Task.Delay(50);
        return AllItems.Where(f => f.ParentId == foo.Id);
    }

    private class FooTree : Foo
    {
        private static readonly Random random = new();

        public IEnumerable<FooTree>? Children { get; set; }

        public bool HasChildren { get; set; }

        public static IEnumerable<FooTree> Generate(IStringLocalizer<Foo> localizer, bool hasChildren = true, int seed = 0) => Enumerable.Range(1, 2).Select(i => new FooTree()
        {
            Id = i + seed,
            Name = localizer["Foo.Name", $"{seed:d2}{(i + seed):d2}"],
            DateTime = System.DateTime.Now.AddDays(i - 1),
            Address = localizer["Foo.Address", $"{random.Next(1000, 2000)}"],
            Count = random.Next(1, 100),
            Complete = random.Next(1, 100) > 50,
            Education = random.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middel,
            HasChildren = hasChildren
        }).ToList();
    }

    private class EditFooTree : Foo
    {
        private static readonly Random random = new();

        [NotNull]
        public List<EditFooTree>? AllItems { get; set; }

        public int ParentId { get; set; }

        public IEnumerable<EditFooTree>? Children { get; set; }

        public bool HasChildren => AllItems.Any(i => i.ParentId == Id);

        public static IEnumerable<EditFooTree> Generate(IStringLocalizer<Foo> localizer, List<EditFooTree> list, int seed = 0, int parentId = 0) => Enumerable.Range(1, 2).Select(i => new EditFooTree()
        {
            Id = i + seed,
            ParentId = parentId,
            Name = localizer["Foo.Name", $"{seed:d2}{(i + seed):d2}"],
            DateTime = System.DateTime.Now.AddDays(i - 1),
            Address = localizer["Foo.Address", $"{random.Next(1000, 2000)}"],
            Count = random.Next(1, 100),
            AllItems = list
        }).ToList();
    }
}

B 站相关视频链接

交流群

QQ Group:BootstrapAdmin & Blazor 795206915 675147445 Welcome to join the group discussion
Themes
Bootstrap
Motronic
Ant Design (完善中)
LayUI (完善中)
An error has occurred. This application may no longer respond until reloaded. Reload