Win UI3开发笔记(四)设置主题

Win UI3设置主题过程

参考文章网址:https://blog.csdn.net/white_night_SZTU/article/details/132819719
核心代码:

rootElement.RequestedTheme = ElementTheme.Dark;
//这和在前端设置控件的 RequestedTheme="Dark"属性是一样的

结果:可以改变按钮或控件的字体颜色。
但是如果当前页面自定义了颜色就不能更改,而且不能改变标题栏的颜色。

//xaml中指定如果在此置顶颜色则无法更改
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"

github上也有类似的:https://github.com/microsoft/microsoft-ui-xaml/issues/6938,其中是导航栏中的文字在黑暗模式下会变白,但是整个导航栏不会,经建议在grid属性中加上

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<NavigationView/>
</Grid>

但是如果我想在黑暗和明亮时自定义不同的颜色,该怎么实现呢?
由此引出官方文档中给出的资源字典。
官方主题资源相关文档:
https://learn.microsoft.com/zh-cn/windows/apps/design/style/xaml-resource-dictionary
你可以使用 XAML 为你的应用定义 UI 或资源。 资源通常是一些你预期多次使用的对象的定义。 为了在以后引用 XAML 资源,你为资源指定一个键,用于充当其名称。 你可以在整个应用中或从应用中的任意 XAML 页面引用资源。 你可以使用 Windows 运行时 XAML 中的 ResourceDictionary 元素定义你的资源。 然后,可使用 StaticResource 标记扩展或 ThemeResource 标记扩展来引用你的资源。
你最希望声明为 XAML 资源的 XAML 元素包括 Style、ControlTemplate、动画组件和 Brush 子类。 我们在此处介绍如何定义 ResourceDictionary 和键控资源,以及 XAML 资源与你定义为应用或应用包一部分的其他资源有何关系。 我们还介绍资源字典高级功能,如 MergedDictionaries 和 ThemeDictionaries。

当前单个界面的资源使用<Page.Resources>定义并使用StaticResource引用。
所有的资源都要定义x:key
如果没有关键字,定义TargetType="Button"其中的样式会作用于button控件。
添加资源在 Application.OnLaunched方法中添加

还可以单独定义一个资源字典页面,“添加”>新建项目…”>“资源字典”,

 <Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <x:String x:Key="greeting">Hello world</x:String>
    </ResourceDictionary>

主题资源和主题字典:

ThemeDictionaries 内的每个 ResourceDictionary 元素必须具有一个 x:Key 值。 该值是一个字符串,它为相关主题命名,例如 “Default”、“Dark”、“Light”或“HighContrast”。
其中,Light下红色Dark下黑色确实能够在本机两种主题下显示不同的颜色。但是上一个例子中的代码不能改变它的颜色。

XAML 主题资源

可能上述是因为定义的是TextBlock的StaticResource?

原文讲到:在应用加载时和随后每次在运行时更改主题时,发生{ThemeResource}标记扩展评估。仅在应用首次加载 XAML 时评估{StaticResource}标记扩展。

如何自定义主题资源?
原文:
在以下位置使用 {ThemeResource} 标记扩展:Styles、Setters、Control 模板、Property 资源库和 Animations。
注意请勿在你的 ThemeDictionaries 内的资源定义中使用 {ThemeResource} 标记扩展。 改用 {StaticResource} 标记扩展。
winui-gallery中对于主题的设定:

<ComboBox x:Name="themeMode" AutomationProperties.AutomationId="themeModeComboBox" SelectionChanged="themeMode_SelectionChanged">
   <ComboBoxItem Content="Light" Tag="Light" />
    <ComboBoxItem Content="Dark" Tag="Dark" />
    <ComboBoxItem Content="Use system setting" Tag="Default" />
</ComboBox>

private void themeMode_SelectionChanged(object sender, RoutedEventArgs e)
{
    var selectedTheme = ((ComboBoxItem)themeMode.SelectedItem)?.Tag?.ToString();
    var window = WindowHelper.GetWindowForElement(this);
    string color;
    if (selectedTheme != null)
    {
        ThemeHelper.RootTheme = App.GetEnum<ElementTheme>(selectedTheme);
        if (selectedTheme == "Dark")
        {
            TitleBarHelper.SetCaptionButtonColors(window, Colors.White);
            color = selectedTheme;
        }
        else if (selectedTheme == "Light")
        {
            TitleBarHelper.SetCaptionButtonColors(window, Colors.Black);
            color = selectedTheme;
        }
        else
        {
            color = TitleBarHelper.ApplySystemThemeToCaptionButtons(window) == Colors.White  ? "Dark" : "Light";
        }
        // announce visual change to automation
        UIHelper.AnnounceActionForAccessibility(sender as UIElement, $"Theme changed to {color}",
                                                                        "ThemeChangedNotificationActivityId");
    }
}

另一个winui相关的实例中:

var selectedTheme = ((RadioButton)sender)?.Tag?.ToString();
if (selectedTheme != null)
{
    ((sender as RadioButton).XamlRoot.Content as SplitView).RequestedTheme = GetEnum<ElementTheme>(selectedTheme);
}

另一个的实例中:
颜色主题资源的定义

<ResourceDictionary x:Key="Dark">
    <Thickness x:Key="CardBorderThickness">1</Thickness>
    <StaticResource x:Key="CardBorderBrush" ResourceKey="CardStrokeColorDefaultBrush" />
    <StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="TextFillColorPrimaryBrush" />
    <StaticResource x:Key="CardBackgroundBrush" ResourceKey="CardBackgroundFillColorDefaultBrush" />
</ResourceDictionary>

简单地说,现在的问题是如何随意切换主题的时候使得某个元素显示不同的且是自定义的颜色?
参照上述的例子,定义不同模式下的资源字典:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Light">
        <SolidColorBrush x:Key="myBrush" Color="Red"/>
    </ResourceDictionary>
    <ResourceDictionary x:Key="Dark">
        <SolidColorBrush x:Key="myBrush" Color="Blue"/>
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

使用动态资源进行绑定,即ThemeResource

<TextBlock Foreground="{ThemeResource brush}" Text="hello world" VerticalAlignment="Center"/>

这样,使用最开始的方法会自动切换。
但是再次运行页面解析失败了,所以还是定义两个字典文件。
如果是一个页面的背景颜色使用这种方法定义可以吗?
定义字典文件之后引用的时候要在page标签中加Page.resource标签,但是如果定义page的背景颜色在page标签中,如果在page标签中定义背景颜色为字典中定义的动态颜色就会报错。
直接在page中定义grid,定义grid中的背景颜色属性绑定。

下一个问题是自定义标题栏以及右上角三个按钮的背景颜色定义:由于标题栏本身具有的特征是在titlebar文件中定义的,所以可以直接在文件中定义标题栏的背景颜色。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值