Enterprise-level component library based on Bootstrap and Blazor

star nuget master download license repo commit

Table 树形数据展示

表格支持树形数据的展示

当数据中有 Children 字段时会自动展示为树形表格,如果不需要或配置为其他字段可以用 ChildrenColumnName 进行配置。

Demo
Loading...

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

Demo

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

Loading...

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

Demo
@inherits BootstrapComponentBase
@page "/tables/tree"

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

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

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

<Block Title="树形数据展示" Introduction="当数据中有 <code>Children</code> 字段时会自动展示为树形表格,如果不需要或配置为其他字段可以用 <code>ChildrenColumnName</code> 进行配置。">
    <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>
</Block>

<Block Title="层次缩进" Introduction="通过设置 <code>IndentSize</code> 以控制每一层的缩进宽度。">
    <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>
</Block>

<Block Title="具有单表维护功能的树形数据" Introduction="实现简单的增、删、改、查功能。">
    <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="@OnTreeExpandQuary">
        <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>
</Block>
// 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 BootstrapBlazor.Shared.Pages.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.Pages.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>> OnTreeExpandQuary(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( Full) 675147445 Welcome to join the group discussion
Themes
Bootstrap
Ant Design (完善中)
Bluma (完善中)
LayUI (完善中)
Motronic (已集成)
An error has occurred. This application may no longer respond until reloaded. Reload