UWP中如何实现跟随系统及应用主题动态切换TextBlock前景色?
Got it, let's solve that problem where your PriceText color doesn't update immediately when the system or app theme changes. The issue with your current code is it only sets the color once on page load—we need to make it react dynamically whenever the theme shifts. Here are two solid approaches:
Approach 1: Use Theme Dictionaries (Recommended)
This is the most idiomatic UWP way, leveraging XAML's built-in theme support to avoid manual event handling.
Step 1: Define Theme-Specific Resources in App.xaml
Add these resource dictionaries to your App.xaml to define the foreground colors for light and dark themes:
<Application.Resources> <!-- Light theme brush --> <ResourceDictionary x:Key="LightThemeResources"> <SolidColorBrush x:Key="PriceTextForeground" Color="DarkGreen"/> </ResourceDictionary> <!-- Dark theme brush --> <ResourceDictionary x:Key="DarkThemeResources"> <SolidColorBrush x:Key="PriceTextForeground" Color="LightGreen"/> </ResourceDictionary> <!-- Merge default styles --> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ms-appx:///Styles/Generic.xaml"/> <!-- Add any other resource dictionaries you use here --> </ResourceDictionary.MergedDictionaries> </Application.Resources>
Step 2: Bind the Brush to Your TextBlock
Update your XAML to use the themed resource directly—no code-behind needed for initial or dynamic color changes:
<TextBlock x:Name="PriceText" Text="This is a Text" Foreground="{StaticResource PriceTextForeground}"/>
Step 3: Sync with App-Level Theme Switching
If your ThemeSelectorService changes the app's theme, make sure it updates Application.Current.RequestedTheme—this will automatically trigger the theme dictionary swap:
// Inside your ThemeSelectorService public static void SetTheme(ElementTheme newTheme) { Theme = newTheme; Application.Current.RequestedTheme = newTheme switch { ElementTheme.Dark => ApplicationTheme.Dark, ElementTheme.Light => ApplicationTheme.Light, _ => ApplicationTheme.Default }; // Optional: Persist the theme setting to local storage ApplicationData.Current.LocalSettings.Values["SelectedTheme"] = newTheme.ToString(); }
Approach 2: Event-Driven Code-Behind
If you need more control (e.g., dynamic color calculations), you can listen for theme change events and update the color manually.
Step 1: Subscribe to Theme Change Events
In your page's constructor, subscribe to both system theme changes and your app's internal theme selector events:
public MainPage() { InitializeComponent(); // Listen for system theme changes Application.Current.RequestedThemeChanged += OnSystemThemeChanged; // Listen for app-internal theme changes (assuming your service has this event) ThemeSelectorService.ThemeChanged += OnAppThemeChanged; // Set initial color UpdatePriceTextColor(); }
Step 2: Implement Update Logic
Add methods to update the color and handle the events:
private void UpdatePriceTextColor() { bool isDark; var appTheme = ThemeSelectorService.Theme; if (appTheme == ElementTheme.Default) { // Fall back to system theme isDark = Application.Current.RequestedTheme == ApplicationTheme.Dark; } else { isDark = appTheme == ElementTheme.Dark; } PriceText.Foreground = new SolidColorBrush(isDark ? Colors.LightGreen : Colors.DarkGreen); } private void OnSystemThemeChanged(Application sender, RequestedThemeChangedEventArgs args) { // Update on UI thread DispatcherQueue.TryEnqueue(UpdatePriceTextColor); } private void OnAppThemeChanged(object sender, EventArgs e) { DispatcherQueue.TryEnqueue(UpdatePriceTextColor); }
Step 3: Clean Up Subscriptions
Don't forget to unsubscribe when the page is navigated away from to avoid memory leaks:
protected override void OnNavigatedFrom(NavigationEventArgs e) { base.OnNavigatedFrom(e); Application.Current.RequestedThemeChanged -= OnSystemThemeChanged; ThemeSelectorService.ThemeChanged -= OnAppThemeChanged; }
Note for Your ThemeSelectorService
Make sure your service raises a ThemeChanged event whenever the selected theme updates:
public static event EventHandler ThemeChanged; private static ElementTheme _selectedTheme; public static ElementTheme Theme { get => _selectedTheme; set { if (_selectedTheme != value) { _selectedTheme = value; ThemeChanged?.Invoke(null, EventArgs.Empty); // Update app theme if needed // ... } } }
Either approach will make your PriceText color update instantly when the system or app theme changes—no page reload required!
内容的提问来源于stack exchange,提问作者Akiya Xiao

