
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)
{
if (item.Id == 0)
{
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();
}
}
}