From b3980280240bea0c73b04c1bc0329ae1c970dd52 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 11:48:00 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E6=9C=AA?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=9A=84=E4=B8=8B=E8=BD=BD=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor b/src/BootstrapBlazor/Components/Table/Table.razor index 228baa0b6..6434fcfe0 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor +++ b/src/BootstrapBlazor/Components/Table/Table.razor @@ -91,18 +91,10 @@ } -- Gitee From 92824fde9478e7372ec632f340fa0758d8276d2b Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 12:03:19 +0800 Subject: [PATCH 2/7] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0=E6=8F=8F=E8=BF=B0?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs | 2 +- src/BootstrapBlazor/Components/Table/Table.razor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs index 90ba2e555..4108341b7 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Pagination.cs @@ -54,7 +54,7 @@ public partial class Table } /// - /// 异步查询回调方法 + /// 异步查询回调方法,设置 后无法触发此回调方法 /// [Parameter] public Func>>? OnQueryAsync { get; set; } diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index cc883b6bc..a4b2bab9d 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -477,7 +477,7 @@ public partial class Table : BootstrapComponentBase, IDisposable, ITable public RenderFragment>? FooterTemplate { get; set; } /// - /// 获得/设置 数据集合,适用于无功能时仅做数据展示使用,高级功能时请使用 回调委托 + /// 获得/设置 数据集合,适用于无功能仅做数据展示使用,高级功能时请使用 回调委托 /// [Parameter] public IEnumerable? Items { get; set; } -- Gitee From b07abeb47c8dbe92c31ab8dcdbf29ac6be54e5d5 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 14:59:16 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20Lambda=20?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95=E8=8E=B7=E5=BE=97=20Key=20?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E5=B1=9E=E6=80=A7=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/LambdaExtensions.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs index 4b96bdd27..c54c622db 100644 --- a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs +++ b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs @@ -3,6 +3,7 @@ // Website: https://www.blazor.zone or https://argozhang.github.io/ using BootstrapBlazor.Components; +using System.ComponentModel.DataAnnotations; using System.Linq.Expressions; using System.Reflection; @@ -600,4 +601,24 @@ public static class LambdaExtensions return false; } #endregion + + /// + /// 获得 指定模型标记 的属性值 + /// + /// + /// + /// + public static Expression> GetKeyValue(TModel model) + { + var type = model is not null ? model.GetType() : typeof(TModel); + Expression> ret = _ => default!; + var property = type.GetRuntimeProperties().FirstOrDefault(p => p.IsDefined(typeof(KeyAttribute))); + if (property != null) + { + var param = Expression.Parameter(typeof(TModel)); + var body = Expression.Property(Expression.Convert(param, type), property); + ret = Expression.Lambda>(Expression.Convert(body, typeof(TValue)), param); + } + return ret; + } } -- Gitee From 2c4aeb90a5d4ad7d276beed2f8730b4119866b27 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 14:59:40 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Services/CacheManager.cs | 19 +++++++++++++++++++ src/BootstrapBlazor/Utils/Utility.cs | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index dce57592f..186edade2 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -301,6 +301,25 @@ internal class CacheManager : ICacheManager }); invoker(model, value); } + + /// + /// 获得 指定模型标记 的属性值 + /// + /// + /// + /// + /// + public static TValue GetKeyValue(TModel model) + { + var type = model is object o ? o.GetType() : typeof(TModel); + var cacheKey = ($"Lambda-GetKeyValue-{type.FullName}", typeof(TModel)); + var invoker = Instance.GetOrCreate(cacheKey, entry => + { + entry.SetDynamicAssemblyPolicy(type); + return LambdaExtensions.GetKeyValue(model).Compile(); + }); + return invoker(model); + } #endregion #region Lambda Sort diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs index e6586f194..e9944f00c 100644 --- a/src/BootstrapBlazor/Utils/Utility.cs +++ b/src/BootstrapBlazor/Utils/Utility.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; +using System.ComponentModel.DataAnnotations; using System.Data; using System.Linq.Expressions; using System.Reflection; @@ -31,6 +32,15 @@ public static class Utility /// public static string GetDisplayName(Type modelType, string fieldName) => CacheManager.GetDisplayName(modelType, fieldName); + /// + /// 获得 指定模型标记 的属性值 + /// + /// + /// + /// + /// + public static TValue GetKeyValue(TModel model) => CacheManager.GetKeyValue(model); + /// /// /// -- Gitee From c194999df38b97e4583d6fb72946984ff1044568 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 14:59:48 +0800 Subject: [PATCH 5/7] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Extensions/UtilityTest.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 test/UnitTest/Extensions/UtilityTest.cs diff --git a/test/UnitTest/Extensions/UtilityTest.cs b/test/UnitTest/Extensions/UtilityTest.cs new file mode 100644 index 000000000..907e22267 --- /dev/null +++ b/test/UnitTest/Extensions/UtilityTest.cs @@ -0,0 +1,22 @@ +// 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.Shared; + +namespace UnitTest.Extensions; + +public class UtilityTest : BootstrapBlazorTestBase +{ + [Fact] + public void GetKeyValue_Ok() + { + var foo = new Foo() { Id = 1 }; + var v = Utility.GetKeyValue(foo); + Assert.Equal(1, v); + + object foo1 = new Foo() { Id = 2 }; + v = Utility.GetKeyValue(foo1); + Assert.Equal(2, v); + } +} -- Gitee From 4c546cbf35d0d0e514139a3733326e8343cee4a8 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 15:36:52 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=A1=8C=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=90=8E=E5=AF=BC=E8=87=B4=E5=B7=A5=E5=85=B7=E6=A0=8F?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E6=8C=89=E9=92=AE=E4=BB=8D=E7=84=B6=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Table/Table.razor.Edit.cs | 148 +++++++++++------- 1 file changed, 91 insertions(+), 57 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs index d95af7842..5a0a503e6 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs @@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms; +using System.ComponentModel.DataAnnotations; +using System.Reflection; namespace BootstrapBlazor.Components; @@ -414,15 +416,18 @@ public partial class Table /// protected async Task QueryData() { + // 目前设计使用 Items 参数后不回调 OnQueryAsync 方法 if (Items == null) { if (OnQueryAsync == null && DynamicContext != null && typeof(TItem).IsAssignableTo(typeof(IDynamicObject))) { + // 动态数据 QueryItems = DynamicContext.GetItems().Cast(); TotalCount = QueryItems.Count(); } else { + // 数据集合 await OnQuery(); } } @@ -462,6 +467,9 @@ public partial class Table TotalCount = queryData.TotalCount; IsAdvanceSearch = queryData.IsAdvanceSearch; + // 处理选中行逻辑 + ProcessSelectedRows(); + // 分页情况下内部不做处理防止页码错乱 if (!queryOption.IsPage) { @@ -473,83 +481,109 @@ public partial class Table await ProcessTreeData(); } } - } - void ProcessPageData(QueryData queryData, QueryPageOptions queryOption) - { - var filtered = queryData.IsFiltered; - var sorted = queryData.IsSorted; - var searched = queryData.IsSearch; - - // 外部未处理 SearchText 模糊查询 - if (!searched && queryOption.Searchs.Any()) + void ProcessSelectedRows() { - QueryItems = QueryItems.Where(queryOption.Searchs.GetFilterFunc(FilterLogic.Or)); - TotalCount = QueryItems.Count(); + // 判断模型是否有 [Key] Id 等可识别字段尝试重构 + if (typeof(TItem).GetRuntimeProperties().Any(p => p.IsDefined(typeof(KeyAttribute)))) + { + var rows = new List(); + // 更新选中行逻辑 + foreach (var item in SelectedRows) + { + var key = Utility.GetKeyValue(item); + if (key != null) + { + if (QueryItems.Any(i => Utility.GetKeyValue(i)?.ToString() == key.ToString())) + { + rows.Add(item); + } + } + } + SelectedRows = rows; + } + else + { + SelectedRows.Clear(); + } } - // 外部未处理自定义高级搜索 内部进行高级自定义搜索过滤 - if (!IsAdvanceSearch && queryOption.CustomerSearchs.Any()) + void ProcessPageData(QueryData queryData, QueryPageOptions queryOption) { - QueryItems = QueryItems.Where(queryOption.CustomerSearchs.GetFilterFunc()); - TotalCount = QueryItems.Count(); - IsAdvanceSearch = true; - } + var filtered = queryData.IsFiltered; + var sorted = queryData.IsSorted; + var searched = queryData.IsSearch; - // 外部未过滤,内部自行过滤 - if (!filtered && queryOption.Filters.Any()) - { - QueryItems = QueryItems.Where(queryOption.Filters.GetFilterFunc()); - TotalCount = QueryItems.Count(); - } + // 外部未处理 SearchText 模糊查询 + if (!searched && queryOption.Searchs.Any()) + { + QueryItems = QueryItems.Where(queryOption.Searchs.GetFilterFunc(FilterLogic.Or)); + TotalCount = QueryItems.Count(); + } - // 外部未处理排序,内部自行排序 - // 先处理列头排序 再处理默认多列排序 - if (!sorted) - { - if (queryOption.SortOrder != SortOrder.Unset && !string.IsNullOrEmpty(queryOption.SortName)) + // 外部未处理自定义高级搜索 内部进行高级自定义搜索过滤 + if (!IsAdvanceSearch && queryOption.CustomerSearchs.Any()) { - var invoker = Utility.GetSortFunc(); - QueryItems = invoker(QueryItems, queryOption.SortName, queryOption.SortOrder); + QueryItems = QueryItems.Where(queryOption.CustomerSearchs.GetFilterFunc()); + TotalCount = QueryItems.Count(); + IsAdvanceSearch = true; } - else if (queryOption.SortList != null && queryOption.SortList.Any()) + + // 外部未过滤,内部自行过滤 + if (!filtered && queryOption.Filters.Any()) { - var invoker = Utility.GetSortListFunc(); - QueryItems = invoker(QueryItems, queryOption.SortList); + QueryItems = QueryItems.Where(queryOption.Filters.GetFilterFunc()); + TotalCount = QueryItems.Count(); } - } - } - async Task ProcessTreeData() - { - KeySet.Clear(); - if (TableTreeNode.HasKey) - { - CheckExpandKeys(TreeRows); - } - if (KeySet.Count > 0) - { - TreeRows = new List>(); - foreach (var item in QueryItems) + // 外部未处理排序,内部自行排序 + // 先处理列头排序 再处理默认多列排序 + if (!sorted) { - var node = new TableTreeNode(item) + if (queryOption.SortOrder != SortOrder.Unset && !string.IsNullOrEmpty(queryOption.SortName)) { - HasChildren = CheckTreeChildren(item), - }; - node.IsExpand = node.HasChildren && node.Key != null && KeySet.Contains(node.Key); - if (node.IsExpand) + var invoker = Utility.GetSortFunc(); + QueryItems = invoker(QueryItems, queryOption.SortName, queryOption.SortOrder); + } + else if (queryOption.SortList != null && queryOption.SortList.Any()) { - await RestoreIsExpand(node); + var invoker = Utility.GetSortListFunc(); + QueryItems = invoker(QueryItems, queryOption.SortList); } - TreeRows.Add(node); } } - else + + async Task ProcessTreeData() { - TreeRows = QueryItems.Select(item => new TableTreeNode(item) + KeySet.Clear(); + if (TableTreeNode.HasKey) + { + CheckExpandKeys(TreeRows); + } + if (KeySet.Count > 0) { - HasChildren = CheckTreeChildren(item) - }).ToList(); + TreeRows = new List>(); + foreach (var item in QueryItems) + { + var node = new TableTreeNode(item) + { + HasChildren = CheckTreeChildren(item), + }; + node.IsExpand = node.HasChildren && node.Key != null && KeySet.Contains(node.Key); + if (node.IsExpand) + { + await RestoreIsExpand(node); + } + TreeRows.Add(node); + } + } + else + { + TreeRows = QueryItems.Select(item => new TableTreeNode(item) + { + HasChildren = CheckTreeChildren(item) + }).ToList(); + } } } } -- Gitee From 3f41fa58937b3ea9488160b7990ecf818e78fdd5 Mon Sep 17 00:00:00 2001 From: Argo-Tianyi Date: Tue, 8 Mar 2022 15:37:14 +0800 Subject: [PATCH 7/7] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor.Shared/Samples/Table/TablesSelection.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor.Shared/Samples/Table/TablesSelection.razor b/src/BootstrapBlazor.Shared/Samples/Table/TablesSelection.razor index 680652ec0..b9e671d43 100644 --- a/src/BootstrapBlazor.Shared/Samples/Table/TablesSelection.razor +++ b/src/BootstrapBlazor.Shared/Samples/Table/TablesSelection.razor @@ -26,4 +26,4 @@ } - + -- Gitee