views:

267

answers:

2

I'm making a WPF application that is going to have multiple skins branded in by our build system. Ideally we would like the application to list off the skins available as some builds will have one to many skins.

At runtime is there a way to enumerate all the Resource Dictionaries in a specific folder?

I want to avoid hard coding the XAML filenames in my codebehind as this is a changing situation.

A: 

You can add ResourceDictionary at runtime.

Resources.MergedDictionaries.Add(...)
Jobi Joy
I don't know the names of the skin so I need to list them first before adding them.
Jippers
A: 

Sort of.

You can enumerate all BAML (compiled XAML) files as follows:

  var resourcesName = assembly.GetName().Name + ".g";
  var manager = new System.Resources.ResourceManager(resourcesName, assembly);
  var resourceSet = manager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
  var allXamlFiles =
    from entry in resourceSet.OfType<DictionaryEntry>()
    let fileName = (string)entry.Key
    where fileName.EndsWith(".baml")
    select fileName.Substring(0, fileName.Length-5) + ".xaml";

There is no way to know which ones of these are ResourceDictionaries and which are other XAML such as Windows or UserControls without actually loading them. So the answer to your direct question is "no" unless you load each XAML you find to check if it is a ResourceDictionary. This would be very slow.

On the other hand, if you're willing to use a naming scheme for your ResourceDictionaries, then you can enumerate all BAMLs in your assembly and select whichever match your naming scheme, and trust that they are ResourceDictionaries. Just extend the "where" clause in the above query.

Therefore the answer is "sort of."

Ray Burns
I can understand the concept of what you're getting at, but it's not building for me. I'm assuming "assembly" is from Assemgly.GetExecutingAssembly(). Also the constructor for manager is probably ResourceManager(resourcesName, assembly). However I think the LINQ query isn't right since resourceSet doesn't have an OfType<>() function
Jippers
I copied this from my own working application code, but as I was pasting the code I did some last-minute refactoring and messed up the ResourceManager constructor. I have fixed my answer to correct the bug.
Ray Burns
As for the other error, I think you merely forgot to `using System.Linq;` since the `OfType<>()` extension method is declared there.
Ray Burns