diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor index c7feea66befdd68fd6ef38638a292073abfd7c13..aee6ac4023188d74401d85d08c88d7b67d4f2302 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor @@ -9,7 +9,11 @@ Introduction="@Localizer["TablesSelectionNormalIntro"]" Name="Normal">
- +
保持选中行状态:
+
选中的行数:@SelectedItems.Count
+ +
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor.cs index 6809e66602e7bbbf97b93df3a3bc9a5d9d5476e6..b9b5ba838f9e778cf0c8e26ad77b0ede94b12e45 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesSelection.razor.cs @@ -19,6 +19,9 @@ public partial class TablesSelection [NotNull] private List? SelectedItems { get; set; } + + private bool IsKeepSelectedRows; + private static IEnumerable PageItemsSource => new int[] { 4, diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs index afa6ee28d1ed2d086bed817f2d8a92acbfb734c9..e8fe798428dfaa17488cdf12df1fbc640782e9eb 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Checkbox.cs @@ -18,6 +18,26 @@ public partial class Table .AddClass(HeaderStyle.ToDescriptionString(), HeaderStyle != TableHeaderStyle.None) .Build(); + /// + /// 是否保持选择行,默认为否。 + /// 最少要有一种行对比的回落机制,否则重新获取数据后无法还原选中状态。 + /// 保持行状态回落机制(优先级从高到低): + /// + /// + /// ModelEqualityComparer + /// + /// + /// CustomKeyAttribute + /// + /// + /// IEqualityComparer<TItem> Equals 重载方法 + /// + /// + /// + [Parameter] + public bool IsKeepSelectedRows { get; set; } = false; + + /// /// 获得 表头行是否选中状态 /// @@ -95,14 +115,16 @@ public partial class Table { case CheckboxState.Checked: // select all - SelectedRows.Clear(); + SelectedRows.RemoveAll(x => Rows.Any(a => Equals(a, x))); SelectedRows.AddRange(ShowRowCheckboxCallback == null ? Rows : Rows.Where(ShowRowCheckboxCallback)); + await OnSelectedRowsChanged(); break; case CheckboxState.UnChecked: default: // unselect all - SelectedRows.Clear(); + SelectedRows.RemoveAll(x => Rows.Any(a => Equals(a, x))); + await OnSelectedRowsChanged(); break; } diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs index 82b2247aef3b421a558528855332d5630b0f8ae8..5bf89ec26e9a4747a6646ddc103b2c0b879b3f64 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs @@ -451,8 +451,11 @@ public partial class Table IsAdvanceSearch = queryData.IsAdvanceSearch; QueryItems = queryData.Items ?? Enumerable.Empty(); - // 处理选中行逻辑 - ResetSelectedRows(QueryItems); + if (!IsKeepSelectedRows) + { + // 处理选中行逻辑 + ResetSelectedRows(QueryItems); + } // 分页情况下内部不做处理防止页码错乱 ProcessData(); diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs index 6a25a5e9e8079144d907fa64186ed1ff6a580e74..d9a060ae783e2ddc02175bb3d1eb164fa95d720e 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs @@ -139,8 +139,11 @@ public partial class Table { PageIndex = pageIndex; - // 清空选中行 - SelectedRows.Clear(); + if (!IsKeepSelectedRows) + { + // 清空选中行 + SelectedRows.Clear(); + } // 无刷新查询数据 await QueryAsync(false); diff --git a/test/UnitTest/Components/TableTest.cs b/test/UnitTest/Components/TableTest.cs index adcc2ded732ebb61758c520f2e5efe1465b6a21d..beb17500781f0e3ff57d2031f9c74e8987e5d5ef 100644 --- a/test/UnitTest/Components/TableTest.cs +++ b/test/UnitTest/Components/TableTest.cs @@ -4129,6 +4129,91 @@ public class TableTest : TableTestBase Assert.Empty(checkboxs); } + [Fact] + public async Task KeepSelectedRows_Ok() + { + var localizer = Context.Services.GetRequiredService>(); + var Items = Foo.GenerateFoo(localizer, 6); + var cut = Context.RenderComponent(pb => + { + pb.AddChildContent>(pb => + { + pb.Add(a => a.RenderMode, TableRenderMode.Table); + pb.Add(a => a.IsMultipleSelect, true); + pb.Add(a => a.IsPagination, true); + pb.Add(a => a.IsKeepSelectedRows, true); + pb.Add(a => a.PageItemsSource, new int[] { 2 }); + pb.Add(a => a.OnQueryAsync, options => + { + var total = Items.Count; + var items = Items.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList(); + return Task.FromResult(new QueryData() { Items = items, TotalCount = total, IsSorted = true, IsFiltered = true, IsSearch = true }); + }); + pb.Add(a => a.TableColumns, foo => builder => + { + builder.OpenComponent>(0); + builder.AddAttribute(1, "Field", "Name"); + builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Name", typeof(string))); + builder.CloseComponent(); + }); + }); + }); + + var btn = cut.Find("tbody tr td input"); + await cut.InvokeAsync(() => btn.Click()); + + var checkboxs = cut.FindAll(".is-checked"); + Assert.Single(checkboxs); + + //点击下页按钮翻页 + var nextBtn = cut.Find(".fa-angle-right"); + await cut.InvokeAsync(() => nextBtn.Click()); + + //选中行数为空 + checkboxs = cut.FindAll(".is-checked"); + Assert.Empty(checkboxs); + + //点击下页按钮翻页 + await cut.InvokeAsync(() => nextBtn.Click()); + + //点击表头CheckBox + btn = cut.Find("thead tr th input"); + await cut.InvokeAsync(() => btn.Click()); + + //加上表头的复选框选中,结果有3项 + checkboxs = cut.FindAll(".is-checked"); + Assert.Equal(3, checkboxs?.Count); + + //点击向前按钮翻页 + var prevBtn = cut.Find("i.fa-angle-left"); + await cut.InvokeAsync(() => prevBtn.Click()); + + //恢复选中行数为0 + checkboxs = cut.FindAll(".is-checked"); + Assert.Empty(checkboxs); + + //点击向前按钮翻页 + await cut.InvokeAsync(() => prevBtn.Click()); + + //恢复选中行数为1 + checkboxs = cut.FindAll(".is-checked"); + Assert.Single(checkboxs); + + //点击向后翻页按钮 + await cut.InvokeAsync(() => nextBtn.Click()); + + //恢复选中行数为0 + checkboxs = cut.FindAll(".is-checked"); + Assert.Empty(checkboxs); + + //点击向后翻页按钮 + await cut.InvokeAsync(() => nextBtn.Click()); + + //恢复选中行数为2,加上表头的复选框选中,结果有3项 + checkboxs = cut.FindAll(".is-checked"); + Assert.Equal(3, checkboxs?.Count); + } + [Fact] public void TableColumn_Ok() {