xamlcolorswindows-runtimewinrt-xaml

xaml define color based on another color


I am learning WinRT, and i define a custom theme for my program, including overwriting some of the default colors

Currently i do something like this in my App.xaml

<Application>
    <Application.Resource>
        <ResourceDictionary>
            ...
            <Color x:Key="PrimaryColor">#FF0055A3</Color>
            <Color x:Key="PrimaryColorHighlighShade">#FF1263B0</Color>
            <Color x:Key="PrimaryColorClickShade">#FF2674BD</Color>
            ...
            <SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="{StaticResoruce PrimaryColor}" />
            <SolidColorBrush x:Key="SliderTrackDecreasePointerOverBackgroundThemeBrush" Color="{StaticResoruce PrimaryColorHighlighShade}" />
            <SolidColorBrush x:Key="SliderTrackDecreasePressedBackgroundThemeBrush" Color="{StaticResoruce PrimaryColorClickShade}" />
            ...
        </ResourceDictionary>
    </Application.Resource>

To Get the Highlight shade and ClickShade, i open up photoshop, goto the HSB Slider, and move the S Down and the B up, but i was wondering if i could do this in XAML, so that all i had to do what change the PrimaryColor, and the other colors, where adjusted accordingly.


Solution

  • You can bind to a static resource (see Is it possible to supply a type converter for a static resource in WPF?) and use a value converter to construct a new color based on the color you provide.

    Edit:

    Here is some code to explain:

    The value converter code (for simplicity I always just add red, you can do more complex calculations as you like):

    class ColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is Color)
            {
                var theColor = Color.Add((Color)value, Color.FromArgb(255,255,0,0));
                return theColor;
            }
            else
            {
                return null;
            }
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    My App.Xaml looks like this:

    <Application x:Class="SO_15979100.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:local="clr-namespace:SO_15979100"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <Color x:Key="PrimaryColor">#FF0055A3</Color>
            <local:ColorConverter x:Key="MyConverter" />
            <SolidColorBrush x:Key="PrimaryColorBrush" Color="{StaticResource PrimaryColor}" />
            <SolidColorBrush x:Key="ConvertedPrimaryColorBrush" Color="{Binding Source={StaticResource PrimaryColor}, Converter={StaticResource MyConverter}}" />
        </Application.Resources>
    </Application>
    

    Note that I've included a local namespace to have the converter at hand.

    My main window is defined like this:

    <Window x:Class="SO_15979100.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
        
            <Rectangle Grid.Column="0" Fill="{StaticResource PrimaryColorBrush}" />
            <Rectangle Grid.Column="1" Fill="{StaticResource ConvertedPrimaryColorBrush}" />
        </Grid>
    </Window>
    

    The rectangle on the left is your color, the one on the right is pink.