From 646fe3dab73d98180b787e6e70f7e66ebf93e8f3 Mon Sep 17 00:00:00 2001 From: tom-englert Date: Fri, 15 May 2026 12:04:29 +0200 Subject: [PATCH 1/2] Add filter drop down for project selection when filtering RESX file names --- .../Behaviors/EntityFilter.cs | 10 ++++++++-- .../Visuals/ResourceView.xaml | 10 ++++++++-- .../Visuals/ResourceViewModel.cs | 19 ++++++++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/ResXManager.View/Behaviors/EntityFilter.cs b/src/ResXManager.View/Behaviors/EntityFilter.cs index 0e72dc0d..24ed0a4e 100644 --- a/src/ResXManager.View/Behaviors/EntityFilter.cs +++ b/src/ResXManager.View/Behaviors/EntityFilter.cs @@ -8,6 +8,7 @@ using Microsoft.Xaml.Behaviors; using ResXManager.Infrastructure; +using ResXManager.Model; using Throttle; @@ -50,7 +51,7 @@ private void FilterText_Changed() try { var regex = new Regex(value, RegexOptions.IgnoreCase | RegexOptions.Singleline); - return item => regex.IsMatch(item?.ToString() ?? string.Empty); + return item => Filter(item, regex); } catch (ArgumentException) { @@ -59,7 +60,7 @@ private void FilterText_Changed() try { var regex = new Regex(value.Replace(@"\", @"\\", StringComparison.Ordinal), RegexOptions.IgnoreCase | RegexOptions.Singleline); - return item => regex.IsMatch(item?.ToString() ?? string.Empty); + return item => Filter(item, regex); } catch (ArgumentException) { @@ -68,6 +69,11 @@ private void FilterText_Changed() return null; } + private static bool Filter(object item, Regex regex) + { + return item is ResourceEntity entity && (regex.IsMatch(entity.DisplayName) || regex.IsMatch(entity.ProjectName)); + } + protected override void OnAttached() { base.OnAttached(); diff --git a/src/ResXManager.View/Visuals/ResourceView.xaml b/src/ResXManager.View/Visuals/ResourceView.xaml index 87eb3aab..375dc00a 100644 --- a/src/ResXManager.View/Visuals/ResourceView.xaml +++ b/src/ResXManager.View/Visuals/ResourceView.xaml @@ -107,8 +107,14 @@ VerticalAlignment="Center" HorizontalAlignment="Right" Margin="2,0" /> - + + diff --git a/src/ResXManager.View/Visuals/ResourceViewModel.cs b/src/ResXManager.View/Visuals/ResourceViewModel.cs index cdff085c..e912ac87 100644 --- a/src/ResXManager.View/Visuals/ResourceViewModel.cs +++ b/src/ResXManager.View/Visuals/ResourceViewModel.cs @@ -4,10 +4,12 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.ComponentModel; using System.Composition; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -55,15 +57,30 @@ public ResourceViewModel(ResourceManager resourceManager, IConfiguration configu _performanceTracer = performanceTracer; ResourceTableEntries = SelectedEntities.ObservableSelectMany(entity => entity.Entries); - ResourceTableEntries.CollectionChanged += (_, __) => ResourceTableEntries_CollectionChanged(); + ResourceTableEntries.CollectionChanged += (_, _) => ResourceTableEntries_CollectionChanged(); + + ResourceManager.ResourceEntities.CollectionChanged += (_, _) => ResourceEntities_OnCollectionChanged(); resourceManager.LanguageChanged += ResourceManager_LanguageChanged; } + [Throttled(typeof(DispatcherThrottle))] + private void ResourceEntities_OnCollectionChanged() + { + ProjectNames.Clear(); + ProjectNames.AddRange(ResourceManager.ResourceEntities + .Select(entity => entity.ProjectName) + .Distinct() + .OrderBy(name => name) + .Select(name => $"^{Regex.Escape(name)}$")); + } + internal event EventHandler? ClearFiltersRequest; public ResourceManager ResourceManager { get; } + public ObservableCollection ProjectNames { get; } = new ObservableCollection(); + public IObservableCollection ResourceTableEntries { get; } public ObservableCollection SelectedEntities { get; } = []; From d912fed594395c6373f10e1e0cad6ce5c02a9490 Mon Sep 17 00:00:00 2001 From: tom-englert Date: Fri, 15 May 2026 12:48:43 +0200 Subject: [PATCH 2/2] Fix warnings --- .../Refactorings.cs | 6 ------ src/ResXManager.View/Behaviors/EntityFilter.cs | 2 +- src/ResXManager.View/Visuals/ProjectFilterItem.cs | 15 +++++++++++++++ src/ResXManager.View/Visuals/ResourceView.xaml | 5 +++++ src/ResXManager.View/Visuals/ResourceViewModel.cs | 7 +++---- 5 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 src/ResXManager.View/Visuals/ProjectFilterItem.cs diff --git a/src/ResXManager.VSIX.Compatibility.Shared/Refactorings.cs b/src/ResXManager.VSIX.Compatibility.Shared/Refactorings.cs index e363a2a4..3f9eb123 100644 --- a/src/ResXManager.VSIX.Compatibility.Shared/Refactorings.cs +++ b/src/ResXManager.VSIX.Compatibility.Shared/Refactorings.cs @@ -127,12 +127,6 @@ public bool CanMoveToResource() .Where(entity => !entity.IsWinFormsDesignerResource) .ToList(); - var filter = EntityFilter.BuildFilter(Settings.Default.ResourceFilter); - if (filter != null) - { - entities.RemoveAll(item => !filter(item.ToString())); - } - var projectResources = new HashSet(GetResourceEntriesFromProject(document, entities)); // put resources from the same project on top diff --git a/src/ResXManager.View/Behaviors/EntityFilter.cs b/src/ResXManager.View/Behaviors/EntityFilter.cs index 24ed0a4e..a6d205c3 100644 --- a/src/ResXManager.View/Behaviors/EntityFilter.cs +++ b/src/ResXManager.View/Behaviors/EntityFilter.cs @@ -41,7 +41,7 @@ private void FilterText_Changed() listBox.Items.Filter = BuildFilter(value); } - public static Predicate? BuildFilter(string? value) + private static Predicate? BuildFilter(string? value) { value = value?.Trim(); diff --git a/src/ResXManager.View/Visuals/ProjectFilterItem.cs b/src/ResXManager.View/Visuals/ProjectFilterItem.cs new file mode 100644 index 00000000..7df0c0a1 --- /dev/null +++ b/src/ResXManager.View/Visuals/ProjectFilterItem.cs @@ -0,0 +1,15 @@ +namespace ResXManager.View.Visuals; + +using System.Text.RegularExpressions; + +public class ProjectFilterItem(string displayName) +{ + public string DisplayName { get; } = displayName; + + public string SearchText { get; } = $"^{Regex.Escape(displayName)}$"; + + public override string ToString() + { + return SearchText; + } +} diff --git a/src/ResXManager.View/Visuals/ResourceView.xaml b/src/ResXManager.View/Visuals/ResourceView.xaml index 375dc00a..72e69f34 100644 --- a/src/ResXManager.View/Visuals/ResourceView.xaml +++ b/src/ResXManager.View/Visuals/ResourceView.xaml @@ -114,6 +114,11 @@ ToolTip="{x:Static properties:Resources.ResourceFilterToolTip}" BorderThickness="0" Style="{DynamicResource {x:Static styles:ResourceKeys.ComboBoxStyle}}"> + + + + + diff --git a/src/ResXManager.View/Visuals/ResourceViewModel.cs b/src/ResXManager.View/Visuals/ResourceViewModel.cs index e912ac87..9de4d12d 100644 --- a/src/ResXManager.View/Visuals/ResourceViewModel.cs +++ b/src/ResXManager.View/Visuals/ResourceViewModel.cs @@ -4,12 +4,10 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.ComponentModel; using System.Composition; using System.IO; using System.Linq; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -27,6 +25,7 @@ using ResXManager.View.Tools; using Throttle; + using TomsToolbox.Essentials; using TomsToolbox.ObservableCollections; using TomsToolbox.Wpf; @@ -72,14 +71,14 @@ private void ResourceEntities_OnCollectionChanged() .Select(entity => entity.ProjectName) .Distinct() .OrderBy(name => name) - .Select(name => $"^{Regex.Escape(name)}$")); + .Select(name => new ProjectFilterItem(name))); } internal event EventHandler? ClearFiltersRequest; public ResourceManager ResourceManager { get; } - public ObservableCollection ProjectNames { get; } = new ObservableCollection(); + public ObservableCollection ProjectNames { get; } = []; public IObservableCollection ResourceTableEntries { get; }