WPF颜色主题使用3个级别的颜色属性

qoefvg9y  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(68)

在我们的WPF应用程序中,我们希望实现一个具有三个颜色属性级别的颜色管理系统:
1.原始(静态颜色)
我们有一组静态颜色定义,例如:

  • 颜色/深蓝色-800:#3D4B66
  • 颜色/白色:#FFFFFF
  • ...

1.Semantic(Light and Dark Variants)
语义级别包括两个变体:光明与黑暗例如:
黑暗变种:

  • colors/background/bg-primary:primitive/color/darkblue-800
  • ...

轻型变种:

  • colors/background/bg-primary:基本/颜色/白色
  • ...

1.组件
在组件级别,我们使用语义颜色属性,目的是在XAML组件中专门引用这些语义级别属性。举例来说:

  • 模态/背景:semantic/colors/background/bg-primary

在XAML中,它表示如下:
Colors/Primitive.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Color x:Key="DarkBlue800">#3D4B66</Color>
    <Color x:Key="White">#FFFFFF</Color>
</ResourceDictionary>

颜色/主题/Dark.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="Colors.Background.BgPrimary" Color="{DynamicResource DarkBlue800}"/>
</ResourceDictionary>

颜色/主题/Light.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <SolidColorBrush x:Key="Colors.Background.BgPrimary" Color="{DynamicResource White}"/>
</ResourceDictionary>

颜色/组件.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="Modal.Background" Color="{DynamicResource Colors.Background.BgPrimary}"/>
</ResourceDictionary>

在App.xaml中,我们注册了所有资源:

Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <!-- Themes -->
            <ResourceDictionary Source="Colors/Primitive.xaml"/>
            <ResourceDictionary Source="Colors/Themes/Light.xaml"/>
            <ResourceDictionary Source="Colors/Components.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
/Application.Resources>

问题是SolidColorBrush不能从另一个SolidColorBrush创建:

<SolidColorBrush x:Key="FromSCB" Color="{DynamicResource SomeSolidColorBrush}"/>

如果我尝试使用这样的SolidColorBrush应用程序抛出以下异常:

SolidColorBrush只有Color dependency属性,这就是为什么它不能从另一个SolidColorBrush派生。
我还尝试使用绑定代理(在this article中解释)沿着SolidColorBrushToColorConverter。然而,我遇到了一个问题- DynamicResource不适用于绑定。当使用StaticResource时,它可以工作,但问题是当我切换语义级别时,颜色不会更新。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:converters="clr-namespace:WpfTest.Converters" 
                    xmlns:binding="clr-namespace:WpfTest.BindingProxy">
    <converters:SolidColorBrushToColor x:Key="SolidToColor"/>
    <binding:ColorBindingProxy x:Key="Proxy.Colors.Background.BgPrimary" Data="{DynamicResource Colors.Background.BgPrimary}" />
    <!--DynamicResource throws an exception-->
    <SolidColorBrush x:Key="Modal.Background" Color="{Binding Source={DynamicResource Proxy.Colors.Background.BgPrimary}, Path=Data, Converter={StaticResource SolidToColor}}"/>
</ResourceDictionary>

有什么想法吗?

u0njafvf

u0njafvf1#

尝试使用转换器?您将在ViewModel中使用Converter将WPF元素的Color属性绑定到string NameOfColor
例如

<UserControl.Resources>        
        <conv:StringToColorConverter x:Key="StringToColorConverter"/>
    </UserControl.Resources>
<Button Foreground="{Binding NameOfColor Converter={StaticResource StringToColorConverter}}">

您的Converter类将类似于

public class StringToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.ToString() == "Green")
            {
                return new SolidColorBrush(Colors.SeaGreen);
            }
            else if (value.ToString() == "DarkGreen")
            {
                return new SolidColorBrush(Colors.DarkSeaGreen);
            }
            else if (value.ToString() == "Red")
            {
                return new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
            }
            return new SolidColorBrush(Colors.White);
            
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (string)value;
        }
    }

相关问题