我有一个应用程序,它有一个按钮来拍摄UserControl
的截图。我希望这张截图看起来像是Application.Current.RequestedTheme = ElementTheme.Light
,即使是Application.Current.RequestedTheme == ElementTheme.Dark
。
为此,我将更改请求的UserControl主题,如下面的示例所示:
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#
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;
}
}
}
单击按钮成功地将屏幕截图中的TextBlock
控件从白色更改为黑色,但边框颜色不会改变。
如果我像这样设置边界颜色:
<Border x:Name="Border" BorderThickness="1" BorderBrush="{ThemeResource BorderBrush}">
但是,这不是实际用户控件的选项,因为内容是动态生成的。
如何将颜色设置为代码背后的{ThemeResource BorderBrush}
?
我尝试使用ThemeListener控件,但它似乎只响应应用程序级别的主题更改。
发布于 2022-09-30 08:01:26
我的解决方案是在XAMl中实现在C#中分配的静态样式:
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#
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;
}
}
}
发布于 2022-09-19 14:54:49
XAML处理器使用的ThemeResource
标记扩展没有支持类表示,但是您应该能够获得主题字典的引用并从其中获取资源:
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;
}
发布于 2022-09-16 23:28:05
使用TextFillColorPrimary
直接切换边框颜色。这样您就不需要调用UpdateBrush()
了。
<UserControl
x:Class="TestWinUI3App.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ThemeTest"
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" BorderBrush="{ThemeResource TextFillColorPrimary}">
<TextBlock Text="Theme text"/>
</Border>
</StackPanel>
</UserControl>
更新
如果您需要以编程方式执行此操作:
private void UpdateBrush()
{
foreach (ResourceDictionary themeDictionary in Application.Current.Resources.MergedDictionaries.Select(x => x.ThemeDictionaries))
{
ResourceDictionary? targetDictionary = null;
if (themeDictionary.TryGetValue(RequestedTheme.ToString(), out var requestedThemeDictionary) is true)
{
targetDictionary = requestedThemeDictionary as ResourceDictionary;
}
else if (themeDictionary.TryGetValue(ElementTheme.Default.ToString(), out var defaultThemeDictionary) is true)
{
targetDictionary = defaultThemeDictionary as ResourceDictionary;
}
if (targetDictionary?.TryGetValue("TextFillColorPrimary", out object resource) is true &&
resource is Color color)
{
Border.BorderBrush = new SolidColorBrush(color);
}
}
}
https://stackoverflow.com/questions/73746892
复制相似问题