Martyn Ball
Martyn Ball

Reputation: 4885

WPF: Give a ResourceDictionary a Name

I have got a ResourceDictionary full of PathGeometry's for my Icons, is it possible I can give this ResourceDictionary a name so I can use some C# to view all of my Icons, and just to make things more grouped together?

So I would use one of the PathGeometry's like so for example

App.Current.Resources.Icons["refresh1"] as Geometry

or

App.Current.Resources["Icons"]["refresh1"] as Geometry

Currently I use App.Current.Resources["refresh1"] as Geometry to use one of the PathGeometry's.

Edit: Unclear why this is, well, unclear. Poster below understood the question but was unclear in my reason for wanting to do this. However my reason isn't required, I just want an answer to what I'm asking, not a discussion on WHY do I want to do this.

Upvotes: 2

Views: 2075

Answers (1)

Mark Feldman
Mark Feldman

Reputation: 16119

This is one of those very straightforward questions that people will spend more time arguing about than answering! :) People can argue the merit of it as much as they like but once you start doing things like dynamically loading ResourceDictionaries (say, from external plugin DLLs) topics like this suddenly become very relevant indeed!

To answer your question, yes, of course this is possible. The main caveat here is that if you just add ResourceDictionaries to your application resources dictionary then the XAML compiler will get confused about what you're trying to do. The trick here is to explicitly specify a single top-level ResourceDictionary and then add all your resources, including your key'd ResourceDictionaries, as the content of that:

<Application.Resources>

    <ResourceDictionary xmlns:sys="clr-namespace:System;assembly=mscorlib">

        <ResourceDictionary x:Key="Dictionary1">
            <sys:String x:Key="str1a">String 1A</sys:String>
            <sys:String x:Key="str1b">String 1B</sys:String>
            <sys:String x:Key="str1c">String 1C</sys:String>
        </ResourceDictionary>

        <ResourceDictionary x:Key="Dictionary2">
            <sys:String x:Key="str2a">String 2A</sys:String>
            <sys:String x:Key="str2b">String 2B</sys:String>
            <sys:String x:Key="str2c">String 2C</sys:String>
        </ResourceDictionary>

        <!-- All other application resources go here -->

    </ResourceDictionary>

</Application.Resources>

Here's some XAML that statically binds to the dictionaries to show that this method works as intended:

<StackPanel>
    <ListBox ItemsSource="{StaticResource Dictionary1}" DisplayMemberPath="Value" />
    <ListBox ItemsSource="{StaticResource Dictionary2}" DisplayMemberPath="Value" />
</StackPanel>

Result:

enter image description here

If you want to access the resources in code then you'll need to cast the first array lookup to a ResourceDictionary, then index that by the actual item key:

var str = (App.Current.Resources["Dictionary1"] as ResourceDictionary)["str1a"].ToString();

If that's too messy then you can clean it up with a helper class like so:

public class Global
{
    static Global _global = new Global();
    public static Global Dictionaries { get { return _global; } }

    public ResourceDictionary this[string index]
    {
        get { return App.Current.Resources[index] as ResourceDictionary; }
    }
}

Which you would then use like this:

var str = (string)Global.Dictionaries["Dictionary1"]["str1a"];

Upvotes: 3

Related Questions