From f725e117336686b3b53422c576d0709d16584cb5 Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Sat, 22 Nov 2025 21:44:51 +0100 Subject: [PATCH 1/2] Port #4344 --- .../DataGrid/Columns/SelectColumn.cs | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/Core/Components/DataGrid/Columns/SelectColumn.cs b/src/Core/Components/DataGrid/Columns/SelectColumn.cs index 58210bd0d4..071b1ec417 100644 --- a/src/Core/Components/DataGrid/Columns/SelectColumn.cs +++ b/src/Core/Components/DataGrid/Columns/SelectColumn.cs @@ -221,6 +221,15 @@ public DataGridSelectMode SelectMode [Parameter] public override IGridSort? SortBy { get; set; } = null; + /// + /// Gets or sets the equality comparer used to determine whether two grid items are equal. + /// + /// If not set, the default equality comparer for is used. + /// Setting this property allows customization of how grid items are compared for equality, which can affect + /// operations such as selection, filtering, or updating items in the grid. + [Parameter] + public IEqualityComparer? Comparer { get; set; } = null; + /// /// Allows to clear the selection. /// @@ -310,14 +319,23 @@ private async Task AddOrRemoveSelectedItemAsync(TGridItem? item) { if (item != null && (Selectable == null || Selectable.Invoke(item))) { - if (SelectMode is DataGridSelectMode.SingleSticky && _selectedItems.Contains(item)) + if (_selectedItems.Contains(item, Comparer)) { - return; - } + if (SelectMode is DataGridSelectMode.SingleSticky) + { + return; + } + + if (Comparer != null) + { + var toRemove = _selectedItems.First(i => Comparer.Equals(i, item)); + _selectedItems.Remove(toRemove); + } + else + { + _selectedItems.Remove(item); + } - if (SelectedItems.Contains(item)) - { - _selectedItems.Remove(item); SelectAll = false; await CallOnSelectAsync(item, isSelected: false); } @@ -356,12 +374,12 @@ Task CallOnSelectAsync(TGridItem item, bool isSelected) private async Task UpdateSelectedItemsAsync() { - if (!SelectedItems.Any() || InternalGridContext == null || InternalGridContext.Items == null) + if (_selectedItems.Count == 0 || InternalGridContext == null || InternalGridContext.Items == null) { return; } - var itemsToRemove = _selectedItems.Where(item => !InternalGridContext.Items.Contains(item)).ToList(); + var itemsToRemove = _selectedItems.Where(item => !InternalGridContext.Items.Contains(item, Comparer)).ToList(); foreach (var item in itemsToRemove) { await AddOrRemoveSelectedItemAsync(item); @@ -427,15 +445,16 @@ private RenderFragment GetDefaultChildContent() return; } - var selected = _selectedItems.Contains(item) || Property.Invoke(item); + var contained = _selectedItems.Contains(item, Comparer); + var selected = contained || Property.Invoke(item); // Sync with SelectedItems list - if (selected && !_selectedItems.Contains(item)) + if (selected && !contained) { _selectedItems.Add(item); RefreshHeaderContent(); } - else if (!selected && _selectedItems.Contains(item)) + else if (!selected && contained) { _selectedItems.Remove(item); } @@ -524,12 +543,12 @@ private void RefreshHeaderContent() // Using SelectedItems only if (InternalGridContext != null && (Grid.Items != null || Grid.ItemsProvider != null)) { - if (!SelectedItems.Any()) + if (_selectedItems.Count == 0) { return false; } - if (SelectedItems.Take(InternalGridContext.TotalItemCount + 1).Count() == InternalGridContext.TotalItemCount || SelectAll == true) + if (_selectedItems.Count == InternalGridContext.TotalItemCount || SelectAll == true) { return true; } @@ -570,13 +589,13 @@ internal async Task OnClickAllAsync(MouseEventArgs e) await SelectAllChanged.InvokeAsync(SelectAll); } - var count = SelectedItems.Count(); + var count = _selectedItems.Count; // SelectedItems _selectedItems.Clear(); if (SelectAll == true && count != InternalGridContext.TotalItemCount) { // Only add selectable items - _selectedItems.AddRange((InternalGridContext.Grid.Items?.ToList() ?? InternalGridContext.Items) + _selectedItems.AddRange(InternalGridContext.Items .Where(item => Selectable?.Invoke(item) ?? true) ); } From 230f3509f59ced58c34d1baa7fc93eac8d0d356d Mon Sep 17 00:00:00 2001 From: Vincent Baaij Date: Sat, 22 Nov 2025 22:16:02 +0100 Subject: [PATCH 2/2] Add extra tests --- ...entUI.AspNetCore.Components.Scripts.esproj | 3 +- .../DataGrid/SelectColumnTests.razor | 56 ++++++++++++++++++- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/Core.Scripts/Microsoft.FluentUI.AspNetCore.Components.Scripts.esproj b/src/Core.Scripts/Microsoft.FluentUI.AspNetCore.Components.Scripts.esproj index 423628128c..af5fc5f69c 100644 --- a/src/Core.Scripts/Microsoft.FluentUI.AspNetCore.Components.Scripts.esproj +++ b/src/Core.Scripts/Microsoft.FluentUI.AspNetCore.Components.Scripts.esproj @@ -1,8 +1,9 @@ - + dist\ Microsoft.FluentUI.AspNetCore.Components false + false npm run build npm run clean diff --git a/tests/Core/Components/DataGrid/SelectColumnTests.razor b/tests/Core/Components/DataGrid/SelectColumnTests.razor index 08e30c8627..3032317648 100644 --- a/tests/Core/Components/DataGrid/SelectColumnTests.razor +++ b/tests/Core/Components/DataGrid/SelectColumnTests.razor @@ -76,8 +76,6 @@ Assert.Single(SelectedItems); } - - [Fact] public async Task SelectColumnTests_Selectable_SingleSelect_SelectedItems() { @@ -1099,7 +1097,7 @@ // Arrange bool selectAllCalled = false; var people = People.ToList(); - + var selectColumn = new SelectColumn { SelectMode = DataGridSelectMode.Single, @@ -1245,6 +1243,58 @@ Assert.Equal(people[0], selectColumn.SelectedItems.First()); } + // Add a test to cover the Comparer property + [Fact] + public void SelectColumnTests_Comparer_Property() + { + // Arrange + var selectColumn = new SelectColumn(); + // Act + var comparer = EqualityComparer.Create((x, y) => x!.PersonId == y!.PersonId, x => x.PersonId.GetHashCode()); + selectColumn.Comparer = comparer; + // Assert + Assert.Equal(comparer, selectColumn.Comparer); + } + + [Fact] + public async Task SelectColumnTests_SingleSelect_SelectedItemsWithComparer() + { + IEnumerable SelectedItems = new List(); + + IQueryable People = new[] + { + new Person(1, "Jean Martin", new DateOnly(1985, 3, 16)), + new Person(2, "Jean Martin", new DateOnly(1985, 3, 16)), + new Person(3, "Julie Smith", new DateOnly(1958, 10, 10)), + }.AsQueryable(); + + // Arrange + var cut = Render( + @ + + + + ); + + // Pre-Assert + Assert.Empty(cut.FindAll("svg[row-selected]")); + Assert.Empty(SelectedItems); + + // Act - Click and select Row 0 + await ClickOnRowAsync(cut, row: 0); + Assert.Single(cut.FindAll("svg[row-selected]")); + Assert.Single(SelectedItems); + + // Act - Click and select Row 1 + await ClickOnRowAsync(cut, row: 0); + + Assert.Empty(SelectedItems); + } + #pragma warning restore BL0005 /// /// Simulate a key down event on the DataGrid row number .