diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor
index 2317f334116..aa3ffb311da 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor
+++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor
@@ -7,21 +7,49 @@
@Localizer["TablesDynamicDescription"]
+@Localizer["TablesDynamicNoteTitle"]
+@((MarkupString)Localizer["TablesDynamicNoteP1"].Value)
+@((MarkupString)Localizer["TablesDynamicNoteP2"].Value)
+@((MarkupString)Localizer["TablesDynamicNoteP3"].Value)
+private void CreatePageDataContext()
+{
+ _dataTableDynamicContext4 = new DataTableDynamicContext(_pageDataTable, (context, col) =>
+ {
+ var propertyName = col.GetFieldName();
+ })
+ {
+ UseCache = false
+ };
+}
+
+private void UpdatePageDataContext()
+{
+ var table = _dataTableDynamicContext4!.DataTable;
+ table.Rows.Clear();
+
+ foreach (var f in _pageData.Skip((_pageIndex - 1) * _pageItems).Take(_pageItems).ToList())
+ {
+ table.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
+ }
+
+ table.AcceptChanges();
+}
+
-
+
@((MarkupString)Localizer["TablesDynamicEditDescription"].Value)
-
+
- @foreach (var item in SelectedItems)
+ @foreach (var item in _selectedItems)
{
@item.GetValue(nameof(Foo.Name))
}
@@ -31,12 +59,16 @@
-
@@ -44,6 +76,6 @@
-
-
+
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs
index 53cb293a61b..3821d350c6e 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs
@@ -12,16 +12,13 @@ namespace BootstrapBlazor.Server.Components.Samples.Table;
///
public partial class TablesDynamic
{
- [NotNull]
- private DataTableDynamicContext? DataTableDynamicContext { get; set; }
-
- private DataTable UserData { get; } = new DataTable();
-
- private List
SelectedItems { get; set; } = [];
-
- private string? ButtonAddColumnText { get; set; }
-
- private string? ButtonRemoveColumnText { get; set; }
+ private DataTableDynamicContext? _dataTableDynamicContext1;
+ private DataTableDynamicContext? _dataTableDynamicContext2;
+ private DataTableDynamicContext? _dataTableDynamicContext3;
+ private DataTableDynamicContext? _dataTableDynamicContext4;
+ private List _selectedItems = [];
+ private string? _buttonAddColumnText;
+ private string? _buttonRemoveColumnText;
///
/// OnInitialized 方法
@@ -30,22 +27,50 @@ protected override void OnInitialized()
{
base.OnInitialized();
- ButtonAddColumnText ??= Localizer["TablesDynamicDynamicColButtonAddColumnText"];
- ButtonRemoveColumnText ??= Localizer["TablesDynamicDynamicColButtonRemoveColumnText"];
-
- // 初始化 DataTable
- InitDataTable();
+ _buttonAddColumnText ??= Localizer["TablesDynamicDynamicColButtonAddColumnText"];
+ _buttonRemoveColumnText ??= Localizer["TablesDynamicDynamicColButtonRemoveColumnText"];
- // 初始化分页表格
- InitPageDataTable();
+ InitDataTableContext();
}
- private static bool ModelEqualityComparer(IDynamicObject x, IDynamicObject y) => x.GetValue("Id")?.ToString() == y.GetValue("Id")?.ToString();
+ private DataTable CreateDataTable()
+ {
+ var dataTable = new DataTable();
+ dataTable.Columns.Add(nameof(Foo.Id), typeof(int));
+ dataTable.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
+ dataTable.Columns.Add(nameof(Foo.Name), typeof(string));
+ dataTable.Columns.Add(nameof(Foo.Count), typeof(int));
+ dataTable.PrimaryKey =
+ [
+ dataTable.Columns[0]
+ ];
+ dataTable.Columns[0].AutoIncrement = true;
+ Foo.GenerateFoo(FooLocalizer, 10).ForEach(f => { dataTable.Rows.Add(f.Id, f.DateTime, f.Name, f.Count); });
+ dataTable.AcceptChanges();
+
+ return dataTable;
+ }
- private void CreateContext()
+ private void InitDataTableContext()
{
- // 初始化动态类型上下文实例
- DataTableDynamicContext = new DataTableDynamicContext(UserData, (context, col) =>
+ var table = CreateDataTable();
+ _dataTableDynamicContext1 = CreateContext(table);
+
+ table = CreateDataTable();
+ _dataTableDynamicContext2 = CreateContext(table);
+
+ table = CreateDataTable();
+ _dataTableDynamicContext3 = CreateContext(table);
+
+ CreatePageDataTable();
+ _dataTableDynamicContext4 = CreatePageDataContext();
+ }
+
+ private static bool ModelEqualityComparer(IDynamicObject x, IDynamicObject y) =>
+ x.GetValue("Id")?.ToString() == y.GetValue("Id")?.ToString();
+
+ private DataTableDynamicContext CreateContext(DataTable table) => new DataTableDynamicContext(table,
+ (context, col) =>
{
var propertyName = col.GetFieldName();
// 使用 Text 设置显示名称示例
@@ -54,7 +79,10 @@ private void CreateContext()
{
context.AddRequiredAttribute(nameof(Foo.DateTime));
// 使用 AutoGenerateColumnAttribute 设置显示名称示例
- context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), new KeyValuePair[] { new(nameof(AutoGenerateColumnAttribute.Text), FooLocalizer[nameof(Foo.DateTime)].Value) });
+ context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), [
+ new KeyValuePair(nameof(AutoGenerateColumnAttribute.Text),
+ FooLocalizer[nameof(Foo.DateTime)].Value)
+ ]);
}
else if (propertyName == nameof(Foo.Name))
{
@@ -70,176 +98,158 @@ private void CreateContext()
{
col.Filterable = true;
// 使用 DisplayAttribute 设置显示名称示例
- context.AddDisplayAttribute(nameof(Foo.Complete), new KeyValuePair[] { new(nameof(DisplayAttribute.Name), FooLocalizer[nameof(Foo.Complete)].Value) });
+ context.AddDisplayAttribute(nameof(Foo.Complete), [
+ new KeyValuePair(nameof(DisplayAttribute.Name),
+ FooLocalizer[nameof(Foo.Complete)].Value)
+ ]);
}
else if (propertyName == nameof(Foo.Id))
{
col.Ignore = true;
}
})
+ {
+ OnDeleteAsync = items =>
{
- OnDeleteAsync = items =>
+ // 数据源中移除
+ foreach (var item in items)
{
- // 数据源中移除
- foreach (var item in items)
+ var id = item.GetValue(nameof(Foo.Id));
+ if (id != null)
{
- var id = item.GetValue(nameof(Foo.Id));
- if (id != null)
+ var row = table.Rows.Find(id);
+ if (row != null)
{
- var row = UserData.Rows.Find(id);
- if (row != null)
- {
- UserData.Rows.Remove(row);
- }
+ table.Rows.Remove(row);
}
}
+ }
- UserData.AcceptChanges();
- return Task.FromResult(true);
- },
- OnChanged = args =>
+ table.AcceptChanges();
+ return Task.FromResult(true);
+ },
+ OnChanged = args =>
+ {
+ if (args.ChangedType == DynamicItemChangedType.Add)
{
- if (args.ChangedType == DynamicItemChangedType.Add)
- {
- var item = args.Items.First();
- item.SetValue(nameof(Foo.DateTime), DateTime.Today);
- item.SetValue(nameof(Foo.Name), "新建值");
- }
-
- return Task.CompletedTask;
+ var item = args.Items.First();
+ item.SetValue(nameof(Foo.DateTime), DateTime.Today);
+ item.SetValue(nameof(Foo.Name), Localizer["TablesDynamicNewValueText"].Value);
}
- };
- }
- private void InitDataTable()
- {
- UserData.Columns.Add(nameof(Foo.Id), typeof(int));
- UserData.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
- UserData.Columns.Add(nameof(Foo.Name), typeof(string));
- UserData.Columns.Add(nameof(Foo.Count), typeof(int));
- UserData.PrimaryKey =
- [
- UserData.Columns[0]
- ];
- UserData.Columns[0].AutoIncrement = true;
- Foo.GenerateFoo(FooLocalizer, 10).ForEach(f =>
- {
- UserData.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
- });
- CreateContext();
- }
+ return Task.CompletedTask;
+ }
+ };
private Task OnAddColumn()
{
- if (!UserData.Columns.Contains(nameof(Foo.Complete)))
+ var table = _dataTableDynamicContext3!.DataTable;
+ if (!table.Columns.Contains(nameof(Foo.Complete)))
{
- UserData.Columns.Add(nameof(Foo.Complete), typeof(bool));
+ table.Columns.Add(nameof(Foo.Complete), typeof(bool));
// 更新数据
var fs = Foo.GenerateFoo(FooLocalizer, 10);
for (var i = 0; i < fs.Count; i++)
{
- UserData.Rows[i][nameof(Foo.Complete)] = fs[i].Complete;
+ table.Rows[i][nameof(Foo.Complete)] = fs[i].Complete;
}
- CreateContext();
+ table.AcceptChanges();
+ _dataTableDynamicContext3 = CreateContext(table);
StateHasChanged();
}
+
return Task.CompletedTask;
}
private Task OnRemoveColumn()
{
- if (UserData.Columns.Contains(nameof(Foo.Complete)))
+ var table = _dataTableDynamicContext3!.DataTable;
+ if (table.Columns.Contains(nameof(Foo.Complete)))
{
- UserData.Columns.Remove(nameof(Foo.Complete));
- CreateContext();
+ table.Columns.Remove(nameof(Foo.Complete));
+ table.AcceptChanges();
+ _dataTableDynamicContext3 = CreateContext(table);
StateHasChanged();
}
+
return Task.CompletedTask;
}
- private DataTable PageDataTable { get; set; } = new();
-
- private int PageItems { get; set; }
-
- private int TotalCount { get; set; }
-
- private int PageIndex { get; set; } = 1;
-
- private int PageCount { get; set; }
-
- [NotNull]
- private List? PageFoos { get; set; }
+ private int _pageItems;
+ private int _totalCount;
+ private int _pageIndex = 1;
+ private int _pageCount;
+ private readonly List _pageData = [];
+ private readonly DataTable _pageDataTable = new();
- private void InitPageDataTable()
+ private void CreatePageDataTable()
{
- PageDataTable.Columns.Add(nameof(Foo.Id), typeof(int));
- PageDataTable.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
- PageDataTable.Columns.Add(nameof(Foo.Name), typeof(string));
- PageDataTable.Columns.Add(nameof(Foo.Count), typeof(int));
- PageFoos = Foo.GenerateFoo(FooLocalizer, 80);
- TotalCount = PageFoos.Count;
- PageIndex = 1;
- PageItems = 2;
- PageCount = (int)Math.Ceiling(TotalCount / 2.0);
- RebuildPageDataTable();
- RebuildPaginationDataTable();
- }
+ _pageDataTable.Columns.Add(nameof(Foo.Id), typeof(int));
+ _pageDataTable.Columns.Add(nameof(Foo.DateTime), typeof(DateTime));
+ _pageDataTable.Columns.Add(nameof(Foo.Name), typeof(string));
+ _pageDataTable.Columns.Add(nameof(Foo.Count), typeof(int));
+ _pageData.AddRange(Foo.GenerateFoo(FooLocalizer, 80));
+ _totalCount = _pageData.Count;
+ _pageIndex = 1;
+ _pageItems = 2;
+ _pageCount = (int)Math.Ceiling(_totalCount / (double)_pageItems);
- private void RebuildPageDataTable()
- {
- PageDataTable.Rows.Clear();
// 此处代码可以通过数据库获得分页后的数据转化成 DataTable 再给 DynamicContext 即可实现数据库分页
- foreach (var f in PageFoos.Skip((PageIndex - 1) * PageItems).Take(PageItems).ToList())
+ foreach (var f in _pageData.Skip((_pageIndex - 1) * _pageItems).Take(_pageItems).ToList())
{
- PageDataTable.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
+ _pageDataTable.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
}
-
- PageDataTable.AcceptChanges();
+ _pageDataTable.AcceptChanges();
}
+ private DataTableDynamicContext CreatePageDataContext() => new DataTableDynamicContext(_pageDataTable, (context, col) =>
+ {
+ var propertyName = col.GetFieldName();
+ if (propertyName == nameof(Foo.DateTime))
+ {
+ context.AddRequiredAttribute(nameof(Foo.DateTime));
+ // 使用 AutoGenerateColumnAttribute 设置显示名称示例
+ context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), [
+ new KeyValuePair(nameof(AutoGenerateColumnAttribute.Text),
+ FooLocalizer[nameof(Foo.DateTime)].Value)
+ ]);
+ }
+ else if (propertyName == nameof(Foo.Name))
+ {
+ context.AddRequiredAttribute(nameof(Foo.Name), FooLocalizer["Name.Required"]);
+ // 使用 Text 设置显示名称示例
+ col.Text = FooLocalizer[nameof(Foo.Name)];
+ }
+ else if (propertyName == nameof(Foo.Count))
+ {
+ context.AddRequiredAttribute(nameof(Foo.Count));
+ // 使用 DisplayNameAttribute 设置显示名称示例
+ context.AddDisplayNameAttribute(nameof(Foo.Count), FooLocalizer[nameof(Foo.Count)].Value);
+ }
+ else if (propertyName == nameof(Foo.Id))
+ {
+ col.Ignore = true;
+ }
+ })
+ {
+ UseCache = false
+ };
- private void RebuildPaginationDataTable()
+ private void UpdatePageDataContext()
{
- PageDataTable.Rows.Clear();
+ var table = _dataTableDynamicContext4!.DataTable;
+ table.Rows.Clear();
+
// 此处代码可以通过数据库获得分页后的数据转化成 DataTable 再给 DynamicContext 即可实现数据库分页
- foreach (var f in PageFoos.Skip((PageIndex - 1) * PageItems).Take(PageItems).ToList())
+ foreach (var f in _pageData.Skip((_pageIndex - 1) * _pageItems).Take(_pageItems).ToList())
{
- PageDataTable.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
+ table.Rows.Add(f.Id, f.DateTime, f.Name, f.Count);
}
- PageDataTable.AcceptChanges();
- DataTablePageDynamicContext = new DataTableDynamicContext(PageDataTable, (context, col) =>
- {
- var propertyName = col.GetFieldName();
- if (propertyName == nameof(Foo.DateTime))
- {
- context.AddRequiredAttribute(nameof(Foo.DateTime));
- // 使用 AutoGenerateColumnAttribute 设置显示名称示例
- context.AddAutoGenerateColumnAttribute(nameof(Foo.DateTime), new KeyValuePair[] { new(nameof(AutoGenerateColumnAttribute.Text), Localizer[nameof(Foo.DateTime)].Value) });
- }
- else if (propertyName == nameof(Foo.Name))
- {
- context.AddRequiredAttribute(nameof(Foo.Name), Localizer["Name.Required"]);
- // 使用 Text 设置显示名称示例
- col.Text = Localizer[nameof(Foo.Name)];
- }
- else if (propertyName == nameof(Foo.Count))
- {
- context.AddRequiredAttribute(nameof(Foo.Count));
- // 使用 DisplayNameAttribute 设置显示名称示例
- context.AddDisplayNameAttribute(nameof(Foo.Count), Localizer[nameof(Foo.Count)].Value);
- }
- else if (propertyName == nameof(Foo.Id))
- {
- col.Ignore = true;
- }
- });
+ table.AcceptChanges();
}
- [NotNull]
- private DataTableDynamicContext? DataTablePageDynamicContext { get; set; }
-
///
/// 点击页码处理函数
///
@@ -247,8 +257,9 @@ private void RebuildPaginationDataTable()
///
private Task OnPageLinkClick(int pageIndex)
{
- PageIndex = pageIndex;
- RebuildPaginationDataTable();
+ _pageIndex = pageIndex;
+ UpdatePageDataContext();
+
StateHasChanged();
return Task.CompletedTask;
}
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamicObject.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamicObject.razor.cs
index 315234a3452..867216438d1 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamicObject.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamicObject.razor.cs
@@ -66,7 +66,7 @@ private static IEnumerable GenerateDynamicColumn
return ret;
}
- private readonly static Random random = new();
+ private static readonly Random Random = new();
private Task> OnQueryAsync(QueryPageOptions options)
{
@@ -76,13 +76,12 @@ private Task> OnQueryAsync(QueryPageOptions options
return Task.FromResult(new QueryData() { Items = items, TotalCount = 10, IsSorted = true, IsFiltered = true });
}
- private Dictionary GenerateDynamicRowData(int index)
+ private Dictionary GenerateDynamicRowData(int _)
{
var ret = new Dictionary();
- for (int i = 0; i < _dynamicColumnList.Count; i++)
+ foreach (var columnName in _dynamicColumnList)
{
- var columnName = _dynamicColumnList[i];
- object? value = random.Next(1000, 9999);
+ var value = Random.Next(1000, 9999);
ret.Add(columnName, value);
}
return ret;
diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json
index fb60e16b823..b09fbe5fc01 100644
--- a/src/BootstrapBlazor.Server/Locales/en-US.json
+++ b/src/BootstrapBlazor.Server/Locales/en-US.json
@@ -4835,6 +4835,11 @@
"TablesDynamicEditDescription": "By setting the OnChanged callback method of the DataTableDynamicContext instance, the value is automatically set when a new row is created",
"TablesDynamicEditIntro": "Add editing and maintenance functions",
"TablesDynamicEditTitle": "Edit function",
+ "TablesDynamicNewValueText": "New Value",
+ "TablesDynamicNoteP1": "The DataTableDynamicContext object internally uses Emit to convert DataTable rows into dynamic types, so every time a DataTableDynamicContext is created a dynamic assembly is generated under the hood. In real projects you should avoid creating dynamic assemblies repeatedly",
+ "TablesDynamicNoteP2": "You can set the UseCache=\"false\" property of DataTableDynamicContext to disable the internal data cache, and update the DataTable property of DataTableDynamicContext in your own code logic to greatly improve system performance",
+ "TablesDynamicNoteP3": "You can refer to the pagination table sample code. Use CreatePageDataContext to create the DataTableDynamicContext instance. When clicking the pager, only the data is updated, and there is no need to recreate the DataTableDynamicContext instance",
+ "TablesDynamicNoteTitle": "Notes:",
"TablesDynamicPageIntro": "Use Pagination component",
"TablesDynamicPageTitle": "Pagination",
"TablesDynamicTitle": "Table Dynamic"
diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json
index a936bc37cbc..a73b1138679 100644
--- a/src/BootstrapBlazor.Server/Locales/zh-CN.json
+++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json
@@ -4835,6 +4835,11 @@
"TablesDynamicEditDescription": "通过设置 DataTableDynamicContext 实例的 OnChanged 回调方法,新建行时自动设置值",
"TablesDynamicEditIntro": "增加编辑维护功能",
"TablesDynamicEditTitle": "编辑功能",
+ "TablesDynamicNewValueText": "新建值",
+ "TablesDynamicNoteP1": "DataTableDynamicContext 对象底层是通过 Emit 技术将 DataTable 行转成动态类型的,所以每创建一次 DataTableDynamicContext 底层就会创建一个动态程序集,所以实际项目中应该尽量避免重复创建动态程序集",
+ "TablesDynamicNoteP2": "可以通过设置 DataTableDynamicContext 属性 UseCache=\"false\" 关闭内部的数据缓存,在自己的代码逻辑中更新 DataTableDynamicContext 的 DataTable 属性,大大提高系统性能",
+ "TablesDynamicNoteP3": "可以查看分页表格示例代码,通过 CreatePageDataContext 创建 DataTableDynamicContext 实例,点击分页的时候仅更新数据,不需要重新创建 DataTableDynamicContext 实例",
+ "TablesDynamicNoteTitle": "注意事项:",
"TablesDynamicPageIntro": "通过与 Pagination 组件配合实现分页功能",
"TablesDynamicPageTitle": "分页",
"TablesDynamicTitle": "Table 表格"