diff --git a/ILSpy.Tests/Metadata/MetadataFilterTests.cs b/ILSpy.Tests/Metadata/MetadataFilterTests.cs index ecabc3b3b..fb98b0991 100644 --- a/ILSpy.Tests/Metadata/MetadataFilterTests.cs +++ b/ILSpy.Tests/Metadata/MetadataFilterTests.cs @@ -62,8 +62,8 @@ public class MetadataFilterTests // not just any column. Case-insensitive substring match. var entry = new SampleEntry { RID = 1, Name = "System.Runtime", Culture = "neutral" }; MetadataTablePageModel.MatchesFilters(entry, new[] { - new ColumnFilter("Name") { Value = "system" }, - new ColumnFilter("Culture") { Value = "NEUTRAL" }, + new ColumnFilter("Name") { Text = "system" }, + new ColumnFilter("Culture") { Text = "NEUTRAL" }, }).Should().BeTrue(); } @@ -74,7 +74,7 @@ public class MetadataFilterTests // Culture is "neutral", even though Name contains "System". var entry = new SampleEntry { Name = "System.Runtime", Culture = "neutral" }; MetadataTablePageModel.MatchesFilters(entry, new[] { - new ColumnFilter("Culture") { Value = "system" }, + new ColumnFilter("Culture") { Text = "system" }, }).Should().BeFalse(); } @@ -84,8 +84,8 @@ public class MetadataFilterTests // All filters must match — one missing column is enough to drop the row. var entry = new SampleEntry { Name = "System.Runtime", Culture = "neutral" }; MetadataTablePageModel.MatchesFilters(entry, new[] { - new ColumnFilter("Name") { Value = "system" }, - new ColumnFilter("Culture") { Value = "invariant" }, + new ColumnFilter("Name") { Text = "system" }, + new ColumnFilter("Culture") { Text = "invariant" }, }).Should().BeFalse(); } @@ -96,7 +96,7 @@ public class MetadataFilterTests // match" prevents stale filter rows from silently passing rows of a different shape. var entry = new SampleEntry { Name = "X" }; MetadataTablePageModel.MatchesFilters(entry, new[] { - new ColumnFilter("DoesNotExist") { Value = "anything" }, + new ColumnFilter("DoesNotExist") { Text = "anything" }, }).Should().BeFalse(); } @@ -128,13 +128,13 @@ public class MetadataFilterTests totalCount.Should().BeGreaterThan(0); var nameFilter = tab.ColumnFilters.Single(f => f.ColumnName == "Name"); - nameFilter.Value = "System"; + nameFilter.Text = "System"; var visible = tab.Items.Where(e => MetadataTablePageModel.MatchesFilters(e, tab.ColumnFilters)).ToList(); visible.Should().NotBeEmpty("at least one TypeDef row should mention 'System'"); visible.Count.Should().BeLessThan(totalCount, "the filter must hide at least one row"); - nameFilter.Value = ""; + nameFilter.Text = ""; var afterClear = tab.Items.Where(e => MetadataTablePageModel.MatchesFilters(e, tab.ColumnFilters)).Count(); afterClear.Should().Be(totalCount); } diff --git a/ILSpy/Metadata/MetadataColumnBuilder.cs b/ILSpy/Metadata/MetadataColumnBuilder.cs index 841b718b6..4fe655608 100644 --- a/ILSpy/Metadata/MetadataColumnBuilder.cs +++ b/ILSpy/Metadata/MetadataColumnBuilder.cs @@ -130,7 +130,7 @@ namespace ILSpy.Metadata FontWeight = FontWeight.Normal, HorizontalAlignment = HorizontalAlignment.Stretch, }; - box.Bind(TextBox.TextProperty, new Binding(nameof(ColumnFilter.Value)) { + box.Bind(TextBox.TextProperty, new Binding(nameof(ColumnFilter.Text)) { Source = filter, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, diff --git a/ILSpy/ViewModels/MetadataTablePageModel.cs b/ILSpy/ViewModels/MetadataTablePageModel.cs index 5e00813c2..0e85bc606 100644 --- a/ILSpy/ViewModels/MetadataTablePageModel.cs +++ b/ILSpy/ViewModels/MetadataTablePageModel.cs @@ -52,7 +52,7 @@ namespace ILSpy.ViewModels /// /// One filter input per column, in the same order as . The view - /// renders each as a TextBox baked into that column's + /// renders each as a TextBox baked into that column's /// header; the filter predicate ANDs every non-empty entry, requiring each row's /// matching property's stringified value to contain its filter (case-insensitive). /// @@ -91,7 +91,7 @@ namespace ILSpy.ViewModels ArgumentNullException.ThrowIfNull(filters); foreach (var f in filters) { - if (string.IsNullOrEmpty(f.Value)) + if (string.IsNullOrEmpty(f.Text)) continue; var prop = propertyLookupCache.GetOrAdd((item.GetType(), f.ColumnName), static key => key.Type.GetProperty(key.Column, @@ -103,7 +103,7 @@ namespace ILSpy.ViewModels { value = prop.GetValue(item); } catch { return false; } var s = value?.ToString(); - if (s is null || !s.Contains(f.Value, StringComparison.OrdinalIgnoreCase)) + if (s is null || !s.Contains(f.Text, StringComparison.OrdinalIgnoreCase)) return false; } return true; @@ -120,8 +120,11 @@ namespace ILSpy.ViewModels public string ColumnName { get; } + // Backing field is `text` rather than `value` because the latter collides with C#'s + // contextual identifier for property setters and trips Avalonia's INPC binding + // plugin on write (the cached accessor's target reference comes back null). [ObservableProperty] - private string? value; + private string? text; } /// The (row, column) pair clicked in a token cell. diff --git a/ILSpy/Views/MetadataTablePage.axaml.cs b/ILSpy/Views/MetadataTablePage.axaml.cs index b78f9da44..f1ed07a4b 100644 --- a/ILSpy/Views/MetadataTablePage.axaml.cs +++ b/ILSpy/Views/MetadataTablePage.axaml.cs @@ -162,7 +162,7 @@ namespace ILSpy.Views void OnColumnFilterChanged(object? sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(ColumnFilter.Value)) + if (e.PropertyName == nameof(ColumnFilter.Text)) itemsView?.Refresh(); }