3

Basically, how can I create my own set of Colors in a static class or the such so that I can do something like this:

What exists:

<Setter ... Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>

What I want:

<Setter ... Value="{DynamicResource {x:Static MyColors.Color1}}"/>
H.B.
  • 166,899
  • 29
  • 327
  • 400
michael
  • 14,844
  • 28
  • 89
  • 177

3 Answers3

6

Resource Keys can be anything, so you can use a Color as a key and value at the same time:

public static class MyColors
{
    static MyColors()
    {
        App.Current.Resources.Add(MyHighlightColorKey, MyHighlightColorKey);
    }

    public static readonly Color MyHighlightColorKey = Color.FromArgb(255, 0, 88, 0);
}

The static constructor adds the colour using itself as a key to the application resources.

(SystemColors uses SystemResourceKeys internally for every defined colour or brush, you have no access to that class however (which makes sense), alternatively you could subclass ResourceKey if you take issue with using the value as its own key)

You can use it like this:

<TextBox>
    <TextBox.Background>
        <SolidColorBrush Color="{DynamicResource {x:Static local:MyColors.MyHighlightColorKey}}"/>
    </TextBox.Background>
</TextBox>

And if you need to override the key on a local level you can do so as well:

<Window.Resources>
    <Color x:Key="{x:Static local:MyColors.MyHighlightColorKey}" A="255" R="255" G="0" B="0"/>
</Window.Resources>

Edit: If you have lots of colours, brushes and whatnot you could also use reflection to do the resource registering in the constructor (i used fields, if you use properties to expose the data you need to adjust this slightly):

static MyColors()
{
    FieldInfo[] keyFieldInfoArray = typeof(MyColors).GetFields();
    foreach (var keyFieldInfo in keyFieldInfoArray)
    {
        object value = keyFieldInfo.GetValue(null);
        App.Current.Resources.Add(value, value);
    }
}
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • This is exactly what I was wondering. Thank you very much H.B.! – michael Apr 01 '11 at 20:13
  • I'm a bit confused on the part where you add the resource using App.current.resources.add(). What does this actually do? It seems this step is unnecessary when accessing the color using {x:Static local:MyColors.MyHighlightColorKey} – redshift5 Oct 29 '15 at 09:46
  • @redshift5: This adds the colours as resources to the app which allows local overriding, which is why you would not use `x:Static` directly but rather `DynamicResource`. – H.B. Oct 29 '15 at 18:04
  • @H.B. Thanks, I see. Are there any advantages of using `{DynamicResource {x:Static local:MyColors.MyHighlightColorKey}}` vs `{x:Static local:MyColors.MyHighlightColorKey}` ? Or after adding it as a resource could you simply use it like `{DynamicResource MyHighlightColorKey}` ? – redshift5 Oct 30 '15 at 04:45
  • @redshift5: As i was saying, you can only override in a local `ResourceDictionary` if the color is referenced via `{DynamicResource {x:Static ...}}`, if you use `x:Static` directly you will always get the color as it is defined in the class, which is beside the point of it being a resource key in the first place. Regarding `{DynamicResource MyHighlightColorKey}`: That does not work because here `MyHighlightColorKey` would be interpreted as a string key but the color is registered using itself as key. – H.B. Oct 30 '15 at 17:09
4

thought I'd chime in with another option. You can use a Static resource instead by doing something like the following...

public struct MyColors
{
    public static Brush Color1
    {
        get { return Brushes.Red; } // or whatever you like
    }
    public static Brush Color2
    {
        get { return Brushes.Blue; }
    }
}

Then in your XAML, use:

"{x:Static local:MyColors.Color1}"

I've just spent 10 minutes trying to get it to work with a DynamicResource extension, but I can't do it. If anyone knows how (or why) then let us know :)

Tom
  • 3,354
  • 1
  • 22
  • 25
  • I like this, it's much simpler. – BoltClock Mar 30 '11 at 20:18
  • 1
    To use it as a resource you need to add it to a resource dictionary, for `SystemColors` that happens behind the scenes and those resources are not visible at the application level. See my answer for a resource approach. – H.B. Mar 30 '11 at 20:22
1

You can easily do this. You have to define the following class:

public class MyColors
{
    public static string Color1{ get{return "Color1Key";}}
}

and for example in your App.xaml you do:

<Application ...>
    <Application.Resources>
        <Color x:Key="Color1Key">#FF969696</Color>
    </Application.Resources>
</Application>

as the static string is actually just for strong typing I usually don't create such a static class and just use whatever key I defined so this becomes:

<Setter ... Value="{DynamicResource Color1Key}"/>

(I believe you can also use the strong typing in <Color x:Key="{x:Static MyColors.Color1}">#FF969696</Color> but I'm not sure right now...)

(also beware of that for using x:Static you will have to specify the namespace where MyColors sits so this becomes {x:Static local:MyColors.Color1})

Markus Hütter
  • 7,796
  • 1
  • 36
  • 63