[英]How do I handle local theme changes in WinUI3?
I have an app that has a button to take a screenshot of a UserControl
.我有一个应用程序,它有一个按钮可以截取UserControl
的屏幕截图。 I'd like the screenshot to appear as as if Application.Current.RequestedTheme = ElementTheme.Light
, even when Application.Current.RequestedTheme == ElementTheme.Dark
.我希望屏幕截图看起来像Application.Current.RequestedTheme = ElementTheme.Light
,即使Application.Current.RequestedTheme == ElementTheme.Dark
也是如此。
To do this, I am changing the requested theme of the UserControl, like this example:为此,我正在更改 UserControl 的请求主题,如下例所示:
XAML XAML
<UserControl
x:Class="TestWinUI3App.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="BorderBrush" ResourceKey="TextFillColorPrimaryBrush"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="BorderBrush" ResourceKey="TextFillColorPrimaryBrush"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<StaticResource x:Key="BorderBrush" ResourceKey="TextFillColorPrimaryBrush"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel Orientation="Vertical">
<Button Content="Switch theme" Tapped="Button_Tapped"/>
<Border x:Name="Border" BorderThickness="1">
<TextBlock Text="Theme text"/>
</Border>
</StackPanel>
</UserControl>
C# C#
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
namespace TestWinUI3App
{
public sealed partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
UpdateBrush();
}
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
RequestedTheme = RequestedTheme == ElementTheme.Dark ? ElementTheme.Light : ElementTheme.Dark;
UpdateBrush();
}
private void UpdateBrush()
{
Border.BorderBrush = Resources["BorderBrush1"] as SolidColorBrush;
}
}
}
Clicking the button successfully changes TextBlock
controls from white to black as appropriate on the screenshots, but the border colour does not change.单击该按钮成功地将TextBlock
控件从屏幕截图上的白色适当更改为黑色,但边框颜色不会更改。
If I set the border colour like this:如果我这样设置边框颜色:
<Border x:Name="Border" BorderThickness="1" BorderBrush="{ThemeResource BorderBrush}">
It works, however this is not an option for the actual user control as the content is generated dynamically.它可以工作,但是这不是实际用户控件的选项,因为内容是动态生成的。
How do I do the equivalent of setting the colour to {ThemeResource BorderBrush}
in codebehind?如何在代码隐藏中将颜色设置为{ThemeResource BorderBrush}
?
I tried using a ThemeListener control, but it only seems to respond to theme changes at the app level.我尝试使用ThemeListener控件,但它似乎只响应应用程序级别的主题更改。
You need to use ThemeDicionaries
for your custom colors.您需要为自定义 colors 使用ThemeDicionaries
。
<Application
x:Class="How_do_I_handle_local_theme_changes_in_WinUI3.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush
x:Key="CustomTextBlockForegroundThemeBrush"
Color="Red" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush
x:Key="CustomTextBlockForegroundThemeBrush"
Color="Green" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush
x:Key="CustomTextBlockForegroundThemeBrush"
Color="Blue" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
There is no backing class representation for the ThemeResource
markup extension that the XAML processor uses but you should be able to get a reference to the theme dictionary and get the resource from there: XAML 处理器使用的ThemeResource
标记扩展没有支持 class 表示,但您应该能够获取对主题字典的引用并从那里获取资源:
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
RequestedTheme = RequestedTheme == ElementTheme.Dark ? ElementTheme.Light : ElementTheme.Dark;
UpdateBrush();
}
private void UpdateBrush()
{
var themeDictionary = Resources.ThemeDictionaries[ActualTheme.ToString()] as ResourceDictionary;
Border.BorderBrush = themeDictionary["BorderBrush"] as SolidColorBrush;
}
My solution to this was to implement a static style in XAMl that was assigned in C#:我对此的解决方案是在 XAMl 中实现 static 样式,该样式在 C# 中分配:
XAML XAML
<UserControl
x:Class="TestWinUI3App.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="BorderStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="{ThemeResource TextFillColorPrimary}"/>
</Style>
</UserControl.Resources>
<StackPanel Orientation="Vertical">
<Button Content="Switch theme" Tapped="Button_Tapped"/>
<Border x:Name="Border" BorderThickness="1">
<TextBlock Text="Theme text"/>
</Border>
</StackPanel>
</UserControl>
C# C#
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace TestWinUI3App
{
public sealed partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
Border.Style = Resources["BorderStyle"] as Style;
}
private void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
RequestedTheme = RequestedTheme == ElementTheme.Dark ? ElementTheme.Light : ElementTheme.Dark;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.