Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best way to override colours for controls? #2

Closed
geometrikal opened this issue Oct 29, 2019 · 6 comments
Closed

Best way to override colours for controls? #2

geometrikal opened this issue Oct 29, 2019 · 6 comments
Labels
question Further information is requested

Comments

@geometrikal
Copy link

I want to give the buttons a border (in another project that uses the nuget package). How should I override the color key in my own resource dictionary?

For example, in Dark.xaml there is

<m:StaticResource x:Key="ButtonBorderBrush" ResourceKey="SystemControlForegroundTransparentBrush" />

If I want to set this to SystemControlBackgroundBaseMediumHighBrush what is the best way that will still respect the theme settings?

@Kinnara
Copy link
Owner

Kinnara commented Oct 29, 2019

  1. Add a theme dictionary inside the <ui:ThemeResources> element in App.xaml:
<ui:ThemeResources>
    <ui:ThemeResources.ThemeDictionaries>
        <ResourceDictionary x:Key="Dark">

        </ResourceDictionary>
    </ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources>
  1. If you need to reference the built-in resources, merge them first:
<ResourceDictionary x:Key="Dark">
    <ResourceDictionary.MergedDictionaries>
        <ui:DefaultThemeResources Key="Dark" />
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>
  1. Redefine the resource you want to override:
<ResourceDictionary x:Key="Dark">
    <ResourceDictionary.MergedDictionaries>
        <ui:DefaultThemeResources Key="Dark" />
    </ResourceDictionary.MergedDictionaries>
    <ui:StaticResource x:Key="ButtonBorderBrush" ResourceKey="SystemControlBackgroundBaseMediumHighBrush" />
</ResourceDictionary>

Currently this doesn't seem to take effect at design time, but does work at run time. And usually you'll need to override the brushes used by other states (such as ButtonBorderBrushPointerOver) as well.

@geometrikal
Copy link
Author

Thank you.

On more question if I may. If I want to create a new colour that is derived from the accent colour, e.g. if none of the resource accent colours are exactly the right shade, is there an easy way to derive one?

BTW thanks for you work on this library. It is really really helpful, especially ContentDialog.

@Kinnara
Copy link
Owner

Kinnara commented Oct 29, 2019

Glad to hear it's of help. Regarding the question, unfortunately there’s no built-in way to do this. For a starter something like this might work for simple scenarios:

public static class SolidColorBrushHelper
{
    public static readonly DependencyProperty NegativeColorProperty =
        DependencyProperty.RegisterAttached(
            "NegativeColor",
            typeof(Color),
            typeof(SolidColorBrushHelper),
            new PropertyMetadata(Colors.Transparent, OnNegativeColorChanged));

    public static Color GetNegativeColor(SolidColorBrush brush)
    {
        return (Color)brush.GetValue(NegativeColorProperty);
    }

    public static void SetNegativeColor(SolidColorBrush brush, Color value)
    {
        brush.SetValue(NegativeColorProperty, value);
    }

    private static void OnNegativeColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var brush = (SolidColorBrush)d;
        brush.Color = GetNegativeColor((Color)e.NewValue);
    }

    private static Color GetNegativeColor(Color color)
    {
        return Color.FromRgb((byte)(255 - color.R), (byte)(255 - color.G), (byte)(255 - color.B));
    }
}
<SolidColorBrush x:Key="NegativeAccentColorBrush" local:SolidColorBrushHelper.NegativeColor="{DynamicResource SystemAccentColor}" />

@geometrikal
Copy link
Author

geometrikal commented Oct 30, 2019

Thanks, I did a variation on that with another dep prop to set the shading amount and it works.

I notice that some colours don't appear at all in the designer if the keys were overridden as <ui:StaticResource ..>. Change it to <DynamicResource ..> they appear in the designer but though an error when the app runs 😅 It will work if defined as a SolidColorBrush based off a DynamicResource, e.g.

<SolidColorBrush x:Key="ButtonBackground"
                     Color="{DynamicResource SystemBaseLowColor}"
                     Opacity="0.5" />

Also when creating an xaml with <ui:ContentDialog ..> as a base, nothing appears at all in the designer.

@Kinnara
Copy link
Owner

Kinnara commented Oct 30, 2019

Using StaticResource this way is commonly seen in UWP and supported by the designer. Unfortunately in WPF I have to use a hack/workaround to get it working and the designer doesn't like it. To keep things in sync with UWP/WinUI I guess we'll have to live with it for now. Using a SolidColorBrush should work too. One thing to note is that it's probably safer to use Color="{StaticResource SystemBaseLowColor}" here. Using DynamicResource might cause issues mentioned here in the "Troubleshooting theme resources" section.

I've committed a fix for the ContentDialog issue and will push an update to NuGet soon. Thanks for reporting this.

@Sylvain2703
Copy link
Contributor

Sylvain2703 commented Nov 26, 2020

Hello,

Is it still possible to override the default resources by taking into account the theme on v0.9.2?
As DefaultThemeResources doesn't exist anymore, I don't know how to get it works.

In advance, thanks for your help and for this great library!

EDIT: It's okay, I just found

<ui:ThemeResources>
    <ui:ThemeResources.ThemeDictionaries>
        <ResourceDictionary x:Key="Light" ui:ThemeDictionary.Key="Light">
            <StaticResource x:Key="TextControlBorderBrush" ResourceKey="SystemControlForegroundBaseMediumBrush" />
            <StaticResource x:Key="TextControlBorderBrushPointerOver" ResourceKey="SystemControlHighlightBaseMediumHighBrush" />
        </ResourceDictionary>
        <ResourceDictionary x:Key="Dark" ui:ThemeDictionary.Key="Dark">
            <StaticResource x:Key="TextControlBorderBrush" ResourceKey="SystemControlForegroundBaseMediumBrush" />
            <StaticResource x:Key="TextControlBorderBrushPointerOver" ResourceKey="SystemControlHighlightBaseMediumHighBrush" />
        </ResourceDictionary>
        <ResourceDictionary x:Key="HighContrast" ui:ThemeDictionary.Key="HighContrast">
            <StaticResource x:Key="TextControlBorderBrush" ResourceKey="SystemControlForegroundBaseMediumBrush" />
            <StaticResource x:Key="TextControlBorderBrushPointerOver" ResourceKey="SystemControlHighlightBaseMediumHighBrush" />
        </ResourceDictionary>
    </ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources>

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants