From 2952c980b678222955ee1f1a647b6212af91bb74 Mon Sep 17 00:00:00 2001
From: Yair <39923744+yaira2@users.noreply.github.com>
Date: Thu, 5 Feb 2026 19:48:42 -0500
Subject: [PATCH 1/3] Add settings string extraction script and config
j
Constant
---
.../Assets/Data/settings_string_keys.json | 139 +++++++++++++++++
src/Files.App/Constants.cs | 5 +
src/Files.App/Dialogs/SettingsDialog.xaml | 20 +++
src/Files.App/Dialogs/SettingsDialog.xaml.cs | 140 ++++++++++++++++++
src/Files.App/Files.App.csproj | 7 +
.../Scripts/extract_settings_strings.ps1 | 46 ++++++
src/Files.App/Strings/en-US/Resources.resw | 3 +
7 files changed, 360 insertions(+)
create mode 100644 src/Files.App/Assets/Data/settings_string_keys.json
create mode 100644 src/Files.App/Scripts/extract_settings_strings.ps1
diff --git a/src/Files.App/Assets/Data/settings_string_keys.json b/src/Files.App/Assets/Data/settings_string_keys.json
new file mode 100644
index 000000000000..1c3c89ae23db
--- /dev/null
+++ b/src/Files.App/Assets/Data/settings_string_keys.json
@@ -0,0 +1,139 @@
+{
+ "AdvancedPage": [
+ "ExportSettings",
+ "ImportSettings",
+ "EditSettingsFile",
+ "SettingsOpenInLogin",
+ "SettingsLeaveAppRunning",
+ "ShowSystemTrayIcon",
+ "SettingsSetAsDefaultFileManager",
+ "SettingsSetAsOpenDialog",
+ "ShowFlattenOptions",
+ "Advanced",
+ "ExperimentalFeatureFlags"
+ ],
+ "AboutPage": [
+ "SponsorUsOnGitHub",
+ "Documentation",
+ "QuestionsAndDiscussions",
+ "SubmitFeatureRequest",
+ "SubmitBugReport",
+ "OpenLogLocation",
+ "ImproveTranslation",
+ "OpenGitHubRepo",
+ "Privacy",
+ "Feedback",
+ "ThirdPartyLibraries",
+ "About",
+ "HelpAndSupport",
+ "OpenSource"
+ ],
+ "LayoutPage": [
+ "SyncFolderPreferencesAcrossDirectories",
+ "LayoutType",
+ "SortInDescendingOrder",
+ "SortPriority",
+ "GroupInDescendingOrder",
+ "GroupByDateUnit",
+ "TagColumn",
+ "SizeColumn",
+ "TypeColumn",
+ "DateColumn",
+ "DateCreatedColumn",
+ "SortBy",
+ "GroupBy",
+ "Columns",
+ "Layout",
+ "SortingAndGrouping",
+ "DetailsView"
+ ],
+ "GeneralPage": [
+ "Language",
+ "DateFormat",
+ "OpenTabInExistingInstance",
+ "AlwaysSwitchToNewlyOpenedTab",
+ "QuickAccess",
+ "Drives",
+ "NetworkLocations",
+ "FileTags",
+ "RecentFiles",
+ "SettingsMultitaskingAlwaysOpenDualPane",
+ "DualPaneSplitDirection",
+ "ShowOpenInNewTab",
+ "ShowOpenInNewWindow",
+ "ShowOpenInNewPane",
+ "ShowCopyPath",
+ "ShowCreateFolderWithSelection",
+ "ShowCreateAlternateDataStream",
+ "ShowCreateShortcut",
+ "ShowPinToSideBar",
+ "ShowCompressionOptions",
+ "ShowFlattenOptions",
+ "ShowSendToMenu",
+ "ShowOpenTerminal",
+ "ShowEditTagsMenu",
+ "ShowPinToStart",
+ "SettingsContextMenuOverflow",
+ "EnableSmoothScrolling",
+ "StartupSettings",
+ "Widgets",
+ "ContextMenuOptions",
+ "General",
+ "DualPane",
+ "Scrolling"
+ ],
+ "AppearancePage": [
+ "SettingsAppearanceTheme",
+ "BackdropMaterial",
+ "Opacity",
+ "ImageFit",
+ "VerticalAlignment",
+ "HorizontalAlignment",
+ "ShowTabActions",
+ "ShowShelfPaneButtonInAddressBar",
+ "ShowToolbar",
+ "ShowStatusCenterButton",
+ "ShowStatusBar",
+ "BackgroundColor",
+ "BackgroundImage",
+ "Toolbars",
+ "Appearance"
+ ],
+ "FoldersPage": [
+ "SettingsFilesAndFoldersShowHiddenItems",
+ "ShowDotFiles",
+ "ShowProtectedSystemFiles",
+ "ShowAlternateStreams",
+ "SettingsFilesAndFoldersShowFileExtensions",
+ "SettingsFilesAndFoldersShowThumbnails",
+ "ShowCheckboxesWhenSelectingItems",
+ "SettingsOpenItemsWithOneClick",
+ "OpenFolderWithOneClick",
+ "OpenFoldersInNewTab",
+ "ShowConfirmationWhenDeletingItems",
+ "ShowFileExtensionWarning",
+ "SelectFilesAndFoldersOnHover",
+ "DoubleClickBlankSpaceToGoUp",
+ "ScrollToPreviousFolderWhenNavigatingUp",
+ "SizeFormat",
+ "HiddenItems",
+ "OpeningItems",
+ "CalculateFolderSizes",
+ "FilesAndFolders",
+ "Display",
+ "Behaviors"
+ ],
+ "DevToolsPage": [
+ "ConnectToGitHub",
+ "ConnectedToGitHub",
+ "DisplayOpenIDE",
+ "DevTools"
+ ],
+ "ActionsPage": [
+ "Actions",
+ "Commands"
+ ],
+ "TagsPage": [
+ "FileTags"
+ ]
+}
diff --git a/src/Files.App/Constants.cs b/src/Files.App/Constants.cs
index c3a531e502dd..d6bf16fa1e14 100644
--- a/src/Files.App/Constants.cs
+++ b/src/Files.App/Constants.cs
@@ -189,6 +189,11 @@ public static class ResourceFilePaths
/// The path to the json file containing a list of file properties to be loaded in the preview pane.
///
public const string PreviewPaneDetailsPropertiesJsonPath = @"ms-appx:///Assets/Resources/PreviewPanePropertiesInformation.json";
+
+ ///
+ /// The path to the json file containing settings string keys used for localized settings search.
+ ///
+ public const string SettingsStringKeysJsonPath = @"ms-appx:///Assets/Data/settings_string_keys.json";
}
public static class Filesystem
diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml b/src/Files.App/Dialogs/SettingsDialog.xaml
index 451a492f67d2..f63ad612722b 100644
--- a/src/Files.App/Dialogs/SettingsDialog.xaml
+++ b/src/Files.App/Dialogs/SettingsDialog.xaml
@@ -81,6 +81,26 @@
OpenPaneLength="260"
PaneDisplayMode="Left"
SelectionChanged="MainSettingsNavigationView_SelectionChanged">
+
+
+
+
+
+
+
+
+
diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml.cs b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
index 0a1857749ce8..6f1079c367db 100644
--- a/src/Files.App/Dialogs/SettingsDialog.xaml.cs
+++ b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
@@ -5,6 +5,12 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
+using CommunityToolkit.WinUI.Controls;
+using Microsoft.UI.Xaml.Media;
+using System.Threading.Tasks;
+using System.IO;
+using Windows.Storage;
+using Windows.Foundation;
namespace Files.App.Dialogs
{
@@ -15,12 +21,18 @@ public sealed partial class SettingsDialog : ContentDialog, IDialog (FrameworkElement)MainWindow.Instance.Content;
+
+
+
+
public SettingsDialog()
{
InitializeComponent();
MainWindow.Instance.SizeChanged += Current_SizeChanged;
+
UpdateDialogLayout();
+ LoadSettingsKeysAsync();
}
public new async Task ShowAsync()
@@ -79,6 +91,134 @@ private void MainSettingsNavigationView_SelectionChanged(NavigationView sender,
};
}
+ private Dictionary> settingsKeysByPage = new();
+ private Dictionary keyToPage = new();
+ private Dictionary keyToLocalized = new();
+
+ public async void LoadSettingsKeysAsync()
+ {
+ try
+ {
+ var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(Constants.ResourceFilePaths.SettingsStringKeysJsonPath));
+ using var stream = await file.OpenStreamForReadAsync();
+ var dict = await JsonSerializer.DeserializeAsync>>(stream);
+ if (dict != null)
+ {
+ settingsKeysByPage = dict;
+ keyToPage.Clear();
+ keyToLocalized.Clear();
+ var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
+ foreach (var kvp in dict)
+ {
+ foreach (var key in kvp.Value)
+ {
+ keyToPage[key] = kvp.Key;
+ string localized = resourceLoader.GetString(key);
+ if (string.IsNullOrEmpty(localized))
+ localized = key;
+ keyToLocalized[key] = localized;
+ }
+ }
+ }
+ }
+ catch { }
+ }
+
+ private void SettingsSearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
+ {
+ if (args.Reason != AutoSuggestionBoxTextChangeReason.UserInput)
+ return;
+
+ var query = sender.Text?.Trim().ToLowerInvariant() ?? string.Empty;
+
+ // Debounce: Only update suggestions if query changed
+ var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
+ string noResults = resourceLoader.GetString("NoResultsFound");
+ if (string.IsNullOrEmpty(query))
+ {
+ // Show a placeholder for empty search
+ sender.ItemsSource = new List {
+ new SettingSuggestion { Key = null, Localized = noResults }
+ };
+ return;
+ }
+
+ var suggestions = keyToLocalized
+ .Where(kvp => kvp.Value.ToLowerInvariant().Contains(query))
+ .Select(kvp => new SettingSuggestion { Key = kvp.Key, Localized = kvp.Value })
+ .DistinctBy(s => s.Localized)
+ .ToList();
+
+ if (suggestions.Count == 0)
+ {
+ // Show a placeholder for no results
+ sender.ItemsSource = new List {
+ new SettingSuggestion { Key = null, Localized = noResults }
+ };
+ }
+ else
+ {
+ sender.ItemsSource = suggestions;
+ }
+ }
+
+ private class SettingSuggestion
+ {
+ public string Key { get; set; }
+ public string Localized { get; set; }
+ public override string ToString() => Localized;
+ }
+
+ private void SettingsSearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
+ {
+ if (args.SelectedItem is SettingSuggestion suggestion && !string.IsNullOrEmpty(suggestion.Key))
+ {
+ if (keyToPage.TryGetValue(suggestion.Key, out var page))
+ {
+ NavigateToPageByName(page);
+ }
+ }
+
+ // Close the suggestion dropdown
+ sender.IsSuggestionListOpen = false;
+ // Clear the query after a suggestion is chosen
+ sender.Text = string.Empty;
+ }
+
+ private void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
+ {
+ var query = args.QueryText?.Trim().ToLowerInvariant() ?? string.Empty;
+ if (string.IsNullOrEmpty(query))
+ {
+ // Close dropdown and clear text
+ sender.IsSuggestionListOpen = false;
+ sender.Text = string.Empty;
+ return;
+ }
+
+ var match = keyToLocalized.FirstOrDefault(x => x.Value.ToLowerInvariant().Contains(query));
+ if (!string.IsNullOrEmpty(match.Key) && keyToPage.TryGetValue(match.Key, out var page))
+ {
+ NavigateToPageByName(page);
+ }
+
+ // Close dropdown and clear text
+ sender.IsSuggestionListOpen = false;
+ sender.Text = string.Empty;
+ }
+
+ private void NavigateToPageByName(string pageName)
+ {
+ foreach (NavigationViewItem item in MainSettingsNavigationView.MenuItems)
+ {
+ if ((item.Tag as string) == pageName)
+ {
+ MainSettingsNavigationView.SelectedItem = item;
+ break;
+ }
+ }
+ }
+
private void ContentDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
{
MainWindow.Instance.SizeChanged -= Current_SizeChanged;
diff --git a/src/Files.App/Files.App.csproj b/src/Files.App/Files.App.csproj
index 28240e497c9b..761f5b92310e 100644
--- a/src/Files.App/Files.App.csproj
+++ b/src/Files.App/Files.App.csproj
@@ -60,8 +60,15 @@
PreserveNewest
+
+ PreserveNewest
+
+
+
+
+
diff --git a/src/Files.App/Scripts/extract_settings_strings.ps1 b/src/Files.App/Scripts/extract_settings_strings.ps1
new file mode 100644
index 000000000000..808d47053d2c
--- /dev/null
+++ b/src/Files.App/Scripts/extract_settings_strings.ps1
@@ -0,0 +1,46 @@
+# PowerShell script to extract all resource string keys used in settings pages and output as JSON mapping page to keys
+# Place this script in src/Files.App/Scripts and ensure it is referenced in the build process
+
+param(
+ [string]$SettingsPagesPath = (Join-Path $PSScriptRoot "..\Views\Settings"),
+ [string]$OutputPath = (Join-Path $PSScriptRoot "..\Assets\Data\settings_string_keys.json")
+)
+
+$allKeys = @{}
+
+
+Get-ChildItem -Path $SettingsPagesPath -Filter *.xaml -Recurse | ForEach-Object {
+ $page = $_.BaseName
+ $content = Get-Content $_.FullName -Raw
+ $settingsCardPattern = '<(?:wctcontrols:)?SettingsCard[^>]*?Header="\{helpers:ResourceString\s+Name=([a-zA-Z0-9_]+)\}"'
+ $settingsExpanderPattern = '<(?:wctcontrols:)?SettingsExpander[^>]*?Header="\{helpers:ResourceString\s+Name=([a-zA-Z0-9_]+)\}"'
+ $textBlockPattern = '<(?:wctcontrols:)?TextBlock[^>]*?(FontSize\s*=\s*"(24|16)")[^>]*?\{helpers:ResourceString\s+Name=([a-zA-Z0-9_]+)\}'
+ $settingsCardMatches = [regex]::Matches($content, $settingsCardPattern)
+ $settingsExpanderMatches = [regex]::Matches($content, $settingsExpanderPattern)
+ $textBlockMatches = [regex]::Matches($content, $textBlockPattern)
+ $keys = @()
+ foreach ($match in $settingsCardMatches) {
+ $key = $match.Groups[1].Value
+ if ($key -and ($keys -notcontains $key)) {
+ $keys += $key
+ }
+ }
+ foreach ($match in $settingsExpanderMatches) {
+ $key = $match.Groups[1].Value
+ if ($key -and ($keys -notcontains $key)) {
+ $keys += $key
+ }
+ }
+ foreach ($match in $textBlockMatches) {
+ $key = $match.Groups[3].Value
+ if ($key -and ($keys -notcontains $key)) {
+ $keys += $key
+ }
+ }
+ if ($keys.Count -gt 0) {
+ $allKeys[$page] = $keys
+ }
+}
+
+# Output as JSON object
+$allKeys | ConvertTo-Json -Depth 5 | Set-Content -Encoding UTF8 $OutputPath
diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw
index 0f0330f5c51f..1c0d9813f543 100644
--- a/src/Files.App/Strings/en-US/Resources.resw
+++ b/src/Files.App/Strings/en-US/Resources.resw
@@ -189,6 +189,9 @@
Search
+
+ No results found
+
Files you've previously accessed will show up here
From 1a8547cc732e1b0c8dadc97625d29a4b380d0bb8 Mon Sep 17 00:00:00 2001
From: Yair <39923744+yaira2@users.noreply.github.com>
Date: Mon, 9 Feb 2026 17:22:03 -0500
Subject: [PATCH 2/3] Update SettingsDialog.xaml.cs
---
src/Files.App/Dialogs/SettingsDialog.xaml.cs | 110 +++++++++----------
1 file changed, 55 insertions(+), 55 deletions(-)
diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml.cs b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
index 6f1079c367db..71dc6144b5f6 100644
--- a/src/Files.App/Dialogs/SettingsDialog.xaml.cs
+++ b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
@@ -126,39 +126,38 @@ public async void LoadSettingsKeysAsync()
private void SettingsSearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
- if (args.Reason != AutoSuggestionBoxTextChangeReason.UserInput)
- return;
-
- var query = sender.Text?.Trim().ToLowerInvariant() ?? string.Empty;
-
- // Debounce: Only update suggestions if query changed
- var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
- string noResults = resourceLoader.GetString("NoResultsFound");
- if (string.IsNullOrEmpty(query))
+ if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
{
- // Show a placeholder for empty search
- sender.ItemsSource = new List {
- new SettingSuggestion { Key = null, Localized = noResults }
- };
- return;
- }
+ var query = sender.Text?.Trim().ToLowerInvariant() ?? string.Empty;
- var suggestions = keyToLocalized
- .Where(kvp => kvp.Value.ToLowerInvariant().Contains(query))
- .Select(kvp => new SettingSuggestion { Key = kvp.Key, Localized = kvp.Value })
- .DistinctBy(s => s.Localized)
- .ToList();
+ var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
+ string noResults = resourceLoader.GetString("NoResultsFound");
+ if (string.IsNullOrEmpty(query))
+ {
+ // Show a placeholder for empty search
+ sender.ItemsSource = new List {
+ new SettingSuggestion { Key = null, Localized = noResults }
+ };
+ return;
+ }
- if (suggestions.Count == 0)
- {
- // Show a placeholder for no results
- sender.ItemsSource = new List {
- new SettingSuggestion { Key = null, Localized = noResults }
- };
- }
- else
- {
- sender.ItemsSource = suggestions;
+ var suggestions = keyToLocalized
+ .Where(kvp => kvp.Value.ToLowerInvariant().Contains(query))
+ .Select(kvp => new SettingSuggestion { Key = kvp.Key, Localized = kvp.Value })
+ .DistinctBy(s => s.Localized)
+ .ToList();
+
+ if (suggestions.Count == 0)
+ {
+ // Show a placeholder for no results
+ sender.ItemsSource = new List {
+ new SettingSuggestion { Key = null, Localized = noResults }
+ };
+ }
+ else
+ {
+ sender.ItemsSource = suggestions;
+ }
}
}
@@ -171,40 +170,41 @@ private class SettingSuggestion
private void SettingsSearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
{
- if (args.SelectedItem is SettingSuggestion suggestion && !string.IsNullOrEmpty(suggestion.Key))
- {
- if (keyToPage.TryGetValue(suggestion.Key, out var page))
- {
- NavigateToPageByName(page);
- }
- }
-
- // Close the suggestion dropdown
- sender.IsSuggestionListOpen = false;
- // Clear the query after a suggestion is chosen
- sender.Text = string.Empty;
+ // No action needed
}
private void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
var query = args.QueryText?.Trim().ToLowerInvariant() ?? string.Empty;
- if (string.IsNullOrEmpty(query))
- {
- // Close dropdown and clear text
- sender.IsSuggestionListOpen = false;
- sender.Text = string.Empty;
- return;
- }
- var match = keyToLocalized.FirstOrDefault(x => x.Value.ToLowerInvariant().Contains(query));
- if (!string.IsNullOrEmpty(match.Key) && keyToPage.TryGetValue(match.Key, out var page))
+ if (args.ChosenSuggestion is SettingSuggestion suggestion && !string.IsNullOrEmpty(suggestion.Key))
{
- NavigateToPageByName(page);
+ if (keyToPage.TryGetValue(suggestion.Key, out var page))
+ {
+ NavigateToPageByName(page);
+ }
}
+ else
+ {
+ var suggestions = keyToLocalized
+ .Where(x => x.Value.ToLowerInvariant().Contains(query))
+ .Select(x => new SettingSuggestion { Key = x.Key, Localized = x.Value })
+ .DistinctBy(s => s.Localized)
+ .ToList();
- // Close dropdown and clear text
- sender.IsSuggestionListOpen = false;
- sender.Text = string.Empty;
+ if (suggestions.Count == 0)
+ {
+ var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForViewIndependentUse();
+ string noResults = resourceLoader.GetString("NoResultsFound");
+ sender.ItemsSource = new List {
+ new SettingSuggestion { Key = null, Localized = noResults }
+ };
+ }
+ else
+ {
+ sender.ItemsSource = suggestions;
+ }
+ }
}
private void NavigateToPageByName(string pageName)
From 7aae3e175d0fdf6fe6819224bddfa6c04bd7174e Mon Sep 17 00:00:00 2001
From: Yair <39923744+yaira2@users.noreply.github.com>
Date: Mon, 9 Feb 2026 21:40:17 -0500
Subject: [PATCH 3/3] Update SettingsDialog.xaml.cs
---
src/Files.App/Dialogs/SettingsDialog.xaml.cs | 67 +++++++++++++++++++-
1 file changed, 64 insertions(+), 3 deletions(-)
diff --git a/src/Files.App/Dialogs/SettingsDialog.xaml.cs b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
index 71dc6144b5f6..786f08e85175 100644
--- a/src/Files.App/Dialogs/SettingsDialog.xaml.cs
+++ b/src/Files.App/Dialogs/SettingsDialog.xaml.cs
@@ -11,6 +11,8 @@
using System.IO;
using Windows.Storage;
using Windows.Foundation;
+using Windows.UI.Xaml.Automation;
+using Microsoft.UI.Xaml.Automation;
namespace Files.App.Dialogs
{
@@ -173,7 +175,7 @@ private void SettingsSearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSugge
// No action needed
}
- private void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
+ private async void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
var query = args.QueryText?.Trim().ToLowerInvariant() ?? string.Empty;
@@ -181,7 +183,7 @@ private void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggest
{
if (keyToPage.TryGetValue(suggestion.Key, out var page))
{
- NavigateToPageByName(page);
+ await NavigateToPageByName(page, suggestion.Localized);
}
}
else
@@ -207,7 +209,7 @@ private void SettingsSearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggest
}
}
- private void NavigateToPageByName(string pageName)
+ private async Task NavigateToPageByName(string pageName, string? localizedName = null)
{
foreach (NavigationViewItem item in MainSettingsNavigationView.MenuItems)
{
@@ -217,6 +219,65 @@ private void NavigateToPageByName(string pageName)
break;
}
}
+
+ if (localizedName is not null)
+ {
+ await Task.Delay(100); // Wait for UI to render
+ var page = SettingsContentFrame.Content as FrameworkElement;
+ if (page is not null)
+ {
+ var element = FindElementByText(page, localizedName);
+ if (element is not null)
+ {
+ // Check if inside an Expander
+ var expander = FindParent(element);
+ if (expander is not null && !expander.IsExpanded)
+ {
+ expander.IsExpanded = true;
+ await Task.Delay(100); // Wait for animation
+ }
+
+ // Scroll to the element
+ var transform = element.TransformToVisual(SettingsContentScrollViewer);
+ var position = transform.TransformPoint(new Point(0, 0));
+ SettingsContentScrollViewer.ChangeView(null, position.Y, null, false);
+ }
+ }
+ }
+ }
+
+ private FrameworkElement? FindElementByText(FrameworkElement root, string text)
+ {
+ if (root is TextBlock tb && tb.Text == text)
+ return root;
+ if (AutomationProperties.GetName(root) == text)
+ return root;
+ if (root is ContentControl cc && cc.Content is string s && s == text)
+ return root;
+
+ for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
+ {
+ var child = VisualTreeHelper.GetChild(root, i) as FrameworkElement;
+ if (child is not null)
+ {
+ var found = FindElementByText(child, text);
+ if (found is not null)
+ return found;
+ }
+ }
+ return null;
+ }
+
+ private T? FindParent(DependencyObject child) where T : DependencyObject
+ {
+ var parent = VisualTreeHelper.GetParent(child);
+ while (parent is not null)
+ {
+ if (parent is T t)
+ return t;
+ parent = VisualTreeHelper.GetParent(parent);
+ }
+ return null;
}
private void ContentDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)