diff --git a/ILSpy.Tests/Metadata/MetadataFilterRowVerificationTest.cs b/ILSpy.Tests/Metadata/MetadataFilterRowVerificationTest.cs index 7a5862c4c..24e86b0c9 100644 --- a/ILSpy.Tests/Metadata/MetadataFilterRowVerificationTest.cs +++ b/ILSpy.Tests/Metadata/MetadataFilterRowVerificationTest.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Headless.NUnit; using Avalonia.Threading; @@ -108,24 +109,32 @@ public class MetadataFilterRowVerificationTest var totalRows = page.Items.Count; totalRows.Should().BeGreaterThan(0, "TypeDef must have rows for filtering to be observable"); + // The DataGrid's ItemsSource is the DataGridCollectionView wired up by ApplySchema. + // Its Count reflects what the user actually sees on screen — that's the post-filter + // row count we need to assert on, not the predicate evaluated on raw Items. + var view = grid.ItemsSource as DataGridCollectionView; + view.Should().NotBeNull("the metadata grid must expose a DataGridCollectionView so the per-column filter can re-evaluate"); + view!.Count.Should().Be(totalRows, "every row should be visible before any filter is set"); + // === STEP 6: Type "System" into the rendered TextBox === headerBox!.Text = "System"; Dispatcher.UIThread.RunJobs(); nameFilter.Text.Should().Be("System", "setting the rendered TextBox.Text must propagate to ColumnFilter.Text"); - var visibleByPredicate = page.Items.Count(e => MetadataTablePageModel.MatchesFilters(e, page.ColumnFilters)); - visibleByPredicate.Should().BeLessThan(totalRows, - "the predicate must hide at least one TypeDef row when filtering Name on 'System'"); - TestContext.Out.WriteLine($"[VERIFY] After typing 'System': filter='{nameFilter.Text}' visible={visibleByPredicate}/{totalRows}"); + + var expectedVisible = page.Items.Count(e => MetadataTablePageModel.MatchesFilters(e, page.ColumnFilters)); + expectedVisible.Should().BeLessThan(totalRows, + "the predicate must hide at least one TypeDef row when Name contains 'System'"); + view.Count.Should().Be(expectedVisible, + "the live grid view must reflect the filter — typing into the header must shrink the visible-row set, not just update ColumnFilter.Text"); window.CaptureAndShow(label: "step6_typed_System"); // === STEP 7: Clear the filter === headerBox.Text = ""; Dispatcher.UIThread.RunJobs(); nameFilter.Text.Should().BeEmpty("clearing the TextBox must clear the filter"); - var visibleAfterClear = page.Items.Count(e => MetadataTablePageModel.MatchesFilters(e, page.ColumnFilters)); - visibleAfterClear.Should().Be(totalRows, "an empty filter must show every row again"); - TestContext.Out.WriteLine($"[VERIFY] After clearing: filter='{nameFilter.Text}' visible={visibleAfterClear}/{totalRows}"); + view.Count.Should().Be(totalRows, + "clearing the filter must restore every row in the visible grid view"); window.CaptureAndShow(label: "step7_cleared"); } } diff --git a/ILSpy/Views/MetadataTablePage.axaml.cs b/ILSpy/Views/MetadataTablePage.axaml.cs index 195b42f35..643ccbae3 100644 --- a/ILSpy/Views/MetadataTablePage.axaml.cs +++ b/ILSpy/Views/MetadataTablePage.axaml.cs @@ -171,10 +171,13 @@ namespace ILSpy.Views foreach (var c in boundModel.Columns) grid.Columns.Add(c); var model = boundModel; - itemsView = new DataGridCollectionView(model.Items) { - Filter = item => MetadataTablePageModel.MatchesFilters(item, model.ColumnFilters), - }; + itemsView = new DataGridCollectionView(model.Items); grid.ItemsSource = itemsView; + // Assign Filter AFTER attaching to the grid; the DataGridCollectionView's setter + // short-circuits on _filter == value and an object-initializer assignment seems to + // land on a transient state that the grid replaces, so the filter ends up null + // on the live view by the time refresh requests come in. + itemsView.Filter = item => MetadataTablePageModel.MatchesFilters(item, model.ColumnFilters); } void ApplyScrollTarget()