diff --git a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample3.razor b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample3.razor index 94e02a4d..d285843e 100644 --- a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample3.razor +++ b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample3.razor @@ -25,10 +25,10 @@ - - - - + + + + Selected Value: @_selectedValue Selected Values: @(_selectedValues == null ? null : string.Join(", ", _selectedValues)) @@ -36,10 +36,10 @@ @code { - bool _multiSelection = false; - bool _sticky = true; - bool _nested = false; - bool _initiallyExpanded = false; - string? _selectedValue; - IEnumerable? _selectedValues; + private bool _multiSelection = false; + private bool _sticky = true; + private bool _nested = false; + private bool _initiallyExpanded = false; + private string? _selectedValue; + private IEnumerable? _selectedValues; } \ No newline at end of file diff --git a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample5.razor b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample5.razor index 33e18410..20beac66 100644 --- a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample5.razor +++ b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample5.razor @@ -10,7 +10,7 @@ } - @foreach (var state in states) { @@ -18,7 +18,7 @@ } - @@ -38,42 +38,42 @@ - Standard Text - Customized Text - Chip + Standard Text + Customized Text + Chip Value: " - @stringValue + @_stringValue " SelectedValues: HashSet<string> { - @(string.Join(", ", stringValues.Select(x => $"\"{x}\""))) - } - - - - - - - - + @(string.Join(", ", _stringValues.Select(x => $"\"{x}\""))) + } + + + + + + + + - @code { - MudRadioGroup? _radioGroup; - ValuePresenter _valuePresenter = ValuePresenter.Text; - string stringValue { get; set; } = "Nothing selected"; - IEnumerable stringValues { get; set; } = new HashSet() { "Alaska", "California" }; - int? intValue; - IEnumerable intValues { get; set; } = new HashSet() { 2, 3 }; - bool _chipCloseable = false; - Variant _chipVariant = Variant.Filled; - Size _chipSize = Size.Small; - bool _nowrap; +@code { + private MudRadioGroup? _radioGroup; + private ValuePresenter _valuePresenter = ValuePresenter.Text; + private string _stringValue = "Nothing selected"; + private IEnumerable _stringValues = new HashSet() { "Alaska", "California" }; + private int? intValue; + private IEnumerable intValues { get; set; } = new HashSet() { 2, 3 }; + private bool _chipCloseable = false; + private Variant _chipVariant = Variant.Filled; + private Size _chipSize = Size.Small; + private bool _nowrap; public class Complex { diff --git a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample6.razor b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample6.razor index 727793f1..b71d39d8 100644 --- a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample6.razor +++ b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample6.razor @@ -14,18 +14,54 @@ - - - + + + + + + Complex Type with ToStringFunc and Search + + + + + + + + Selected House: + @if (_selectedHouse != null) + { + Number: @_selectedHouse.Number + Name: @_selectedHouse.Name + Postcode: @_selectedHouse.Postcode + } + else + { + None selected + } + + + + @code { bool _multiselection; bool _searchBoxAutoFocus; bool _searchBoxClearable; private string? _selectedState; + private TestHouse? _selectedHouse; private string[] _states = { @@ -45,6 +81,22 @@ "Washington", "West Virginia", "Wisconsin", "Wyoming", }; + private class TestHouse + { + public int Number { get; set; } + public string? Name { get; set; } + public string? Postcode { get; set; } + } + + private List TestHouses = new() + { + new TestHouse { Number = 1, Name = "Test1", Postcode = "12345" }, + new TestHouse { Number = 2, Name = "Test2", Postcode = "54321" }, + new TestHouse { Number = 3, Name = "Test3", Postcode = "67890" }, + new TestHouse { Number = 4, Name = "Test4", Postcode = "09876" }, + new TestHouse { Number = 5, Name = "Test5", Postcode = "11223" }, + }; + private bool SearchItems(string value, string searchString) { if (searchString == "") diff --git a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample7.razor b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample7.razor index e3f4d973..78fe33af 100644 --- a/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample7.razor +++ b/docs/CodeBeam.MudBlazor.Extensions.Docs/Pages/Components/SelectExtended/Examples/SelectExtendedExample7.razor @@ -12,9 +12,9 @@ - Before Search (Default) - Start of the searchbox in the same line - After Search + Before Search (Default) + Start of the searchbox in the same line + After Search @@ -33,11 +33,11 @@ - @code { - ValuePresenter _valuePresenter = ValuePresenter.Text; - SelectAllPosition _selectAllPosition; - string value { get; set; } = "Nothing selected"; - IEnumerable options { get; set; } = new HashSet() { "Alaska", "California" }; +@code { + private ValuePresenter _valuePresenter = ValuePresenter.Text; + private SelectAllPosition _selectAllPosition; + private string value { get; set; } = "Nothing selected"; + private IEnumerable options { get; set; } = new HashSet() { "Alaska", "California" }; private string[] states = { diff --git a/src/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs b/src/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs index a9fb10ad..c465e73e 100644 --- a/src/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs +++ b/src/CodeBeam.MudBlazor.Extensions/Components/ListExtended/MudListExtended.razor.cs @@ -956,7 +956,7 @@ protected internal async Task SearchBoxHandleKeyDownAsync(KeyboardEventArgs obj) await MudSelectExtended.FocusAsync(); } break; - case "Escape": + case "Escape": if (MudSelectExtended != null && MultiSelection == false) { await MudSelectExtended.CloseMenu(); @@ -1783,10 +1783,14 @@ protected internal async ValueTask ScrollToMiddleAsync(MudListItemExtended? if (SearchFunc != null) { - return ItemCollection.Where(x => SearchFunc.Invoke(x, _searchString)).ToList(); + return [.. ItemCollection.Where(x => SearchFunc.Invoke(x, _searchString))]; } - return ItemCollection.Where(x => Converter.Convert(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true).ToList(); + var stringValue = new Func(x => + ToStringFunc != null ? ToStringFunc(x) : Converter.Convert(x) + ); + + return [.. ItemCollection.Where(x => stringValue(x)?.Contains(_searchString, StringComparison.InvariantCultureIgnoreCase) == true)]; } /// @@ -1834,7 +1838,7 @@ protected async Task OnDoubleClickHandler(MouseEventArgs? args, T? itemValue) /// /// protected internal MudListItemExtended? ActiveItem => _lastActivatedItem; - + /// /// /// diff --git a/tests/CodeBeam.MudBlazor.Extensions.UnitTests.Viewer/TestComponents/ListExtended/ListExtendedItemCollectionSearchTest.razor b/tests/CodeBeam.MudBlazor.Extensions.UnitTests.Viewer/TestComponents/ListExtended/ListExtendedItemCollectionSearchTest.razor new file mode 100644 index 00000000..e1d5c1da --- /dev/null +++ b/tests/CodeBeam.MudBlazor.Extensions.UnitTests.Viewer/TestComponents/ListExtended/ListExtendedItemCollectionSearchTest.razor @@ -0,0 +1,26 @@ +@namespace MudExtensions.UnitTests.TestComponents + + + + +@code { + public MudListExtended? List { get; set; } + + public List Houses = new() + { + new TestHouse { Number = 1, Name = "Test1", Postcode = "12345" }, + new TestHouse { Number = 2, Name = "Test2", Postcode = "54321" }, + new TestHouse { Number = 3, Name = "Test3", Postcode = "67890" }, + }; + + public class TestHouse + { + public int Number { get; set; } + public string? Name { get; set; } + public string? Postcode { get; set; } + } +} \ No newline at end of file diff --git a/tests/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs b/tests/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs index 60a83951..98510dfb 100644 --- a/tests/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs +++ b/tests/CodeBeam.MudBlazor.Extensions.UnitTests/Components/ListExtendedTests.cs @@ -363,5 +363,50 @@ public async Task List_SearchChanged_WithNullItemCollection() var finalItems = comp.FindAll("div.mud-list-item-extended").Count; finalItems.Should().Be(9); } + + + [Test] + public void ListExtended_Search_With_ItemCollection_Should_Use_ToStringFunc() + { + // Arrange + var comp = Context.Render(); + var list = comp.FindComponent>().Instance; + + list.SearchBox.Should().BeTrue(); + list.ItemCollection.Should().HaveCount(3); + + // Act - search for "1 - Test1" using reflection to set _searchString + var searchStringField = typeof(MudListExtended) + .GetField("_searchString", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + searchStringField?.SetValue(list, "1 - Test1"); + + var result = list.GetSearchedItems(); + + // Assert - should find item by ToStringFunc format, not class name + result.Should().NotBeNull(); + result.Should().HaveCount(1); + result.First().Number.Should().Be(1); + result.First().Name.Should().Be("Test1"); + } + + [Test] + public void ListExtended_Search_Should_Find_Items_By_Custom_Display_Format_Not_ClassName() + { + // Arrange + var comp = Context.Render(); + var list = comp.FindComponent>().Instance; + + // Act - search for "Test2" (part of the formatted display, not the class name) + var searchStringField = typeof(MudListExtended) + .GetField("_searchString", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + searchStringField?.SetValue(list, "Test2"); + + var result = list.GetSearchedItems(); + + // Assert + result.Should().HaveCount(1); + result.First().Name.Should().Be("Test2"); + result.First().Number.Should().Be(2); + } } } \ No newline at end of file