Skip to content

Commit 8de9a2e

Browse files
Lekco1320ArgoZhang
andauthored
doc(Table): add explain of binding complex object (#4922)
Co-Authored-By: Argo Zhang <[email protected]>
1 parent 4350928 commit 8de9a2e

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumn.razor

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,31 @@
170170
</Table>
171171
</DemoBlock>
172172

173+
<DemoBlock Title="@Localizer["BindComplexObjectTitle"]" Introduction="@Localizer["BindComplexObjectIntro"]" Name="BindComplexObject">
174+
<section ignore>
175+
<p>@((MarkupString)Localizer["BindComplexObjectP1"].Value)</p>
176+
<p>@((MarkupString)Localizer["BindComplexObjectP2"].Value)</p>
177+
<Button OnClick="@OnClickCompanyButton" Text="@Localizer["BindComplexObjectButtonText"]"></Button>
178+
</section>
179+
<Table TItem="ComplexFoo"
180+
IsPagination="true" PageItemsSource="@PageItemsSource" CreateItemCallback="@CreateComplexFoo"
181+
IsStriped="true" IsBordered="true"
182+
ShowToolbar="false" IsMultipleSelect="true" ShowExtendButtons="false"
183+
OnQueryAsync="@OnQueryComplexFooAsync">
184+
<TableColumns>
185+
<TableColumn @bind-Field="@context.DateTime" Text="@Localizer["ComplexFooDateTime"]" Width="120" FormatString="yyyy-MM-dd" />
186+
<TableColumn @bind-Field="@context.Name" Text="@Localizer["ComplexFooName"]" Width="100" />
187+
<TableColumn @bind-Field="@context.Address" Text="@Localizer["ComplexFooAddress"]" />
188+
<TableColumn @bind-Field="@context.Age" Text="@Localizer["ComplexFooAge"]" />
189+
<TableColumn @bind-Field="@context.Company" Text="@Localizer["ComplexFooCompany"]">
190+
<Template Context="v">
191+
<div>@v.Row.Company?.Name</div>
192+
</Template>
193+
</TableColumn>
194+
</TableColumns>
195+
</Table>
196+
</DemoBlock>
197+
173198
<DemoBlock Title="@Localizer["OnColumnCreatingTitle"]" Introduction="@Localizer["OnColumnCreatingIntro"]" Name="OnColumnCreating">
174199
<section ignore>
175200
<Tips class="mb-3">

src/BootstrapBlazor.Server/Components/Samples/Table/TablesColumn.razor.cs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public partial class TablesColumn
1818
[NotNull]
1919
private List<Foo>? Items { get; set; }
2020

21+
[NotNull]
22+
private List<ComplexFoo>? ComplexItems { get; set; }
23+
2124
private static IEnumerable<int> PageItemsSource => new int[] { 5, 10, 20 };
2225

2326
private bool IgnoreColumn { get; set; }
@@ -30,6 +33,7 @@ protected override void OnInitialized()
3033
base.OnInitialized();
3134

3235
Items = Foo.GenerateFoo(FooLocalizer);
36+
ComplexItems = ComplexFoo.GenerateComplexFoo(FooLocalizer);
3337
}
3438

3539
private void OnClickIgnoreColumn() => IgnoreColumn = !IgnoreColumn;
@@ -52,6 +56,10 @@ protected override void OnInitialized()
5256
return Task.FromResult(ret);
5357
}
5458

59+
/// <summary>
60+
/// Foo 类型的异步查询
61+
/// The async query of Items
62+
/// </summary>
5563
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
5664
{
5765
IEnumerable<Foo> items = Items;
@@ -88,6 +96,46 @@ private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions options)
8896
});
8997
}
9098

99+
/// <summary>
100+
/// ComplexItems 的异步查询
101+
/// The async query of ComplexItems
102+
/// </summary>
103+
private Task<QueryData<ComplexFoo>> OnQueryComplexFooAsync(QueryPageOptions options)
104+
{
105+
IEnumerable<ComplexFoo> items = ComplexItems;
106+
107+
// 先处理过滤再处理排序 提高性能
108+
var isFiltered = false;
109+
if (options.Filters.Count != 0)
110+
{
111+
items = items.Where(options.Filters.GetFilterFunc<ComplexFoo>());
112+
isFiltered = true;
113+
}
114+
115+
// 排序
116+
var isSorted = false;
117+
if (!string.IsNullOrEmpty(options.SortName))
118+
{
119+
items = items.Sort(options.SortName, options.SortOrder);
120+
isSorted = true;
121+
}
122+
123+
// 设置记录总数
124+
var total = items.Count();
125+
126+
// 内存分页
127+
items = items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList();
128+
129+
return Task.FromResult(new QueryData<ComplexFoo>()
130+
{
131+
Items = items,
132+
TotalCount = total,
133+
IsSorted = isSorted,
134+
IsFiltered = isFiltered,
135+
IsSearch = true
136+
});
137+
}
138+
91139
private static Task<bool> OnSaveAsync(Foo foo, ItemChangedType changedType) => Task.FromResult(true);
92140

93141
private static Task OnColumnCreating(List<ITableColumn> columns)
@@ -115,4 +163,93 @@ private void SetAlign(ITableColumn column, Alignment alignment)
115163
_dateTimeAlign = alignment;
116164
}
117165
}
166+
167+
/// <summary>
168+
/// 复杂类型 ComplexFoo 的构造回调
169+
/// Construction callback of complex type ComplexFoo
170+
/// </summary>
171+
private ComplexFoo CreateComplexFoo() => ComplexFoo.Generate(FooLocalizer);
172+
173+
/// <summary>
174+
/// 设置 ComplexItems 的 Company 属性
175+
/// Set property Company of ComplexItems
176+
/// </summary>
177+
private Task OnClickCompanyButton()
178+
{
179+
foreach (var complexFoo in ComplexItems)
180+
{
181+
complexFoo.Company = new Company(((char)('A' + Random.Shared.Next(26))).ToString());
182+
}
183+
return Task.CompletedTask;
184+
}
185+
186+
/// <summary>
187+
/// 示例类 Company
188+
/// Class sample Company
189+
/// </summary>
190+
private class Company(string name)
191+
{
192+
public string Name { get; set; } = name;
193+
}
194+
195+
/// <summary>
196+
/// 示例复杂类型 ComplexFoo
197+
/// Complex class sample ComplexFoo
198+
/// </summary>
199+
private class ComplexFoo : Foo
200+
{
201+
public int Age { get; set; }
202+
203+
/// <summary>
204+
/// 业务逻辑无法确保 Company 属性不为 null
205+
/// The business logic cannot ensure that the Company property is not null.
206+
/// </summary>
207+
public Company? Company { get; set; }
208+
209+
/// <summary>
210+
/// ComplexFoo 类不提供无参构造函数
211+
/// Class ComplexFoo does not provide a parameterless constructor
212+
/// </summary>
213+
public ComplexFoo(int age)
214+
{
215+
Age = age;
216+
}
217+
218+
/// <summary>
219+
/// 生成含有随机数据的 ComplexFoo 实例
220+
/// Generate an instance of ComplexFoo with random data
221+
/// </summary>
222+
public static new ComplexFoo Generate(IStringLocalizer<Foo> localizer) => new(Random.Shared.Next(20, 65))
223+
{
224+
Id = 1,
225+
Name = localizer["Foo.Name", "1000"],
226+
DateTime = System.DateTime.Now,
227+
Address = localizer["Foo.Address", $"{Random.Shared.Next(1000, 2000)}"],
228+
Count = Random.Shared.Next(1, 100),
229+
Complete = Random.Shared.Next(1, 100) > 50,
230+
Education = Random.Shared.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middle,
231+
ReadonlyColumn = Random.Shared.Next(10, 50)
232+
};
233+
234+
/// <summary>
235+
/// 生成含有随机数据的 ComplexFoo 实例集合
236+
/// Generate a list of ComplexFoo instances with random data
237+
/// </summary>
238+
/// <returns>
239+
/// 返回一个含有随机数据的 ComplexFoo 实例集合
240+
/// Return a List of ComplexFoo instances with random data
241+
/// </returns>
242+
public static List<ComplexFoo> GenerateComplexFoo(IStringLocalizer<Foo> localizer, int count = 80)
243+
=> Enumerable.Range(1, count).Select(i => new ComplexFoo(Random.Shared.Next(20, 65))
244+
{
245+
Id = i,
246+
Name = localizer["Foo.Name", $"{i:d4}"],
247+
DateTime = System.DateTime.Now.AddDays(i - 1),
248+
Address = localizer["Foo.Address", $"{Random.Shared.Next(1000, 2000)}"],
249+
Count = Random.Shared.Next(1, 100),
250+
Complete = Random.Shared.Next(1, 100) > 50,
251+
Education = Random.Shared.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middle,
252+
ReadonlyColumn = Random.Shared.Next(10, 50)
253+
}).ToList();
254+
}
118255
}

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5050,6 +5050,16 @@
50505050
"ShowCopyColumnDesc": "You can fine-tune the <code>Tooltip</code> related parameters of the copy column data icon by setting <code>ShowCopyColumnTooltip</code> <code>CopyColumnTooltipText</code> <code>CopyColumnCopiedTooltipText</code> and other settings",
50515051
"ShowColumnToolboxTitle": "Column Toolbox",
50525052
"ShowColumnToolboxIntro": "Enable the column toolbar button by setting the <code>ToolboxTemplate</code> parameter",
5053+
"BindComplexObjectTitle": "Bind Complex Types and Expressions",
5054+
"BindComplexObjectIntro": "When binding a complex type, whether the bound object collection is empty or not, the <code>TItem</code> must provide a parameterless constructor. Otherwise, it is required to provide a construction callback through <code>CreateItemCallback</code>. When binding a complex expression, the bound expression must not throw a <code>NullReferenceException</code> exception. If the business logic cannot avoid this issue, it is recommended to handle it using a <code>Template</code>",
5055+
"BindComplexObjectP1": "In this example, the complex type <code>ComplexFoo</code> does not have a parameterless constructor, so a construction callback for <code>ComplexFoo</code> should be provided through <code>CreateItemCallback</code>",
5056+
"BindComplexObjectP2": "In this example, we want to bind a complex expression <code>context.Company.Name</code> to the column <code>CompanyName</code>, but the business logic cannot ensure that the value of the <code>Company</code> property is not <code>null</code> at the time of binding. Therefore, we can first bind a simple expression and then handle it using the column template <code>Template</code>",
5057+
"BindComplexObjectButtonText": "Set company",
5058+
"ComplexFooDateTime": "DateTime",
5059+
"ComplexFooName": "Name",
5060+
"ComplexFooAddress": "Address",
5061+
"ComplexFooAge": "Age",
5062+
"ComplexFooCompany": "Company",
50535063
"OnColumnCreatingTitle": "Set current column properties",
50545064
"OnColumnCreatingIntro": "By specifying <code>OnColumnCreating</code> callback, make secondary data changes to the column collection",
50555065
"OnColumnCreatingP1": "Existing columns can be extended through the parameters in the <code>OnColumnCreating</code> callback method:",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5050,6 +5050,16 @@
50505050
"ShowCopyColumnDesc": "可以通过设置 <code>ShowCopyColumnTooltip</code> <code>CopyColumnTooltipText</code> <code>CopyColumnCopiedTooltipText</code> 等设置微调拷贝列数据图标的 <code>Tooltip</code> 相关参数",
50515051
"ShowColumnToolboxTitle": "列工具栏",
50525052
"ShowColumnToolboxIntro": "通过设置列 <code>ToolboxTemplate</code> 参数,开启列工具栏按钮",
5053+
"BindComplexObjectTitle": "绑定复杂类型和表达式",
5054+
"BindComplexObjectIntro": "当绑定复杂类型时,无论绑定的对象集合是否为空,都要求 <code>TItem</code> 提供无参构造函数,否则要求通过 <code>CreateItemCallback</code> 提供构造回调;当绑定复杂表达式时,要求绑定时该表达式不得引发 <code>NullReferenceException</code> 异常,如果业务逻辑无法避免此问题,建议使用 <code>Template</code> 进行处理",
5055+
"BindComplexObjectP1": "本例中,复杂类型 <code>ComplexFoo</code> 不具备无参构造函数,需通过 <code>CreateItemCallback</code> 提供 <code>ComplexFoo</code> 的构造回调",
5056+
"BindComplexObjectP2": "本例中,我们希望将复杂表达式 <code>context.Company.Name</code> 绑定到列 <code>CompanyName</code> 上,但是业务逻辑无法确保绑定时属性 <code>Company</code> 的值不为 <code>null</code> 。因此可以先绑定简单表达式,再通过列模板 <code>Template</code> 进行处理",
5057+
"BindComplexObjectButtonText": "设置公司",
5058+
"ComplexFooDateTime": "日期",
5059+
"ComplexFooName": "姓名",
5060+
"ComplexFooAddress": "地址",
5061+
"ComplexFooAge": "年龄",
5062+
"ComplexFooCompany": "公司",
50535063
"OnColumnCreatingTitle": "设置当前列属性",
50545064
"OnColumnCreatingIntro": "通过指定 <code>OnColumnCreating</code>回调,对列集合进行数据二次更改",
50555065
"OnColumnCreatingP1": "通过 <code>OnColumnCreating</code> 回调方法中的参数既可以对现有列进行扩展:",

0 commit comments

Comments
 (0)