首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何处理WinUI3中的本地主题更改?

如何处理WinUI3中的本地主题更改?
EN

Stack Overflow用户
提问于 2022-09-16 15:09:32
回答 3查看 121关注 0票数 0

我有一个应用程序,它有一个按钮来拍摄UserControl的截图。我希望这张截图看起来像是Application.Current.RequestedTheme = ElementTheme.Light,即使是Application.Current.RequestedTheme == ElementTheme.Dark

为此,我将更改请求的UserControl主题,如下面的示例所示:

XAML

代码语言:javascript
运行
复制
<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#

代码语言:javascript
运行
复制
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控件从白色更改为黑色,但边框颜色不会改变。

如果我像这样设置边界颜色:

代码语言:javascript
运行
复制
<Border x:Name="Border" BorderThickness="1" BorderBrush="{ThemeResource BorderBrush}">

但是,这不是实际用户控件的选项,因为内容是动态生成的。

如何将颜色设置为代码背后的{ThemeResource BorderBrush}

我尝试使用ThemeListener控件,但它似乎只响应应用程序级别的主题更改。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-09-30 08:01:26

我的解决方案是在XAMl中实现在C#中分配的静态样式:

XAML

代码语言:javascript
运行
复制
<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#

代码语言:javascript
运行
复制
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;
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2022-09-19 14:54:49

XAML处理器使用的ThemeResource标记扩展没有支持类表示,但是您应该能够获得主题字典的引用并从其中获取资源:

代码语言:javascript
运行
复制
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;
}
票数 1
EN

Stack Overflow用户

发布于 2022-09-16 23:28:05

使用TextFillColorPrimary直接切换边框颜色。这样您就不需要调用UpdateBrush()了。

代码语言:javascript
运行
复制
<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>

更新

如果您需要以编程方式执行此操作:

代码语言:javascript
运行
复制
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);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73746892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档