Instant ResourceDictionary xaml from another assembly

I defined a source dictionary in the WPF class library containing colors and brushes called BrushResources.xaml.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Lots of Colors and Brushes here> </ResourceDictionary> 

I want to use some of the Brushes in the code from another assembly that references this library project. How to get a ResourceDictionary instance from this?

+4
source share
4 answers

What you request is a component of the functions necessary to ensure true skinning in the application. Getting resources from a separate assembly involves reading compiled XAML or BAML from another assembly. Here is the method that I use in the skin library to extract BAML from the assembly:

 //Relevant Namespaces: //using System.Windows.Baml2006; //using System.Xaml; public static List<Stream> GetBamlStreams(AssemblyName skinAssemblyName) { List<Stream> bamlStreams = new List<Stream>(); Assembly skinAssembly = Assembly.Load(skinAssemblyName); string[] resourceDictionaries = skinAssembly.GetManifestResourceNames(); foreach (string resourceName in resourceDictionaries) { ManifestResourceInfo info = skinAssembly.GetManifestResourceInfo(resourceName); if (info.ResourceLocation != ResourceLocation.ContainedInAnotherAssembly) { Stream resourceStream = skinAssembly.GetManifestResourceStream(resourceName); using (ResourceReader reader = new ResourceReader(resourceStream)) { foreach (DictionaryEntry entry in reader) { //TODO: Figure out if this is a ResourceDictionary I care about //Key will be name of the RD (BrushResources.baml, in your case) if (IsRelevantResource(entry)) { bamlStreams.Add(entry.Value as Stream); } } } } } return bamlStreams; } 

Then, to convert BAML to specific resources, you do the following:

 //If .NET 3.5, need this initialization: //Type xamlType = typeof(System.Windows.Markup.XamlReader); //LoadBamlMethod = xamlType.GetMethod(LOAD_BAML_METHOD, BindingFlags.NonPublic | BindingFlags.Static); public static T LoadBaml<T>(Stream stream) { //For .net 3.5: //ParserContext parserContext = new ParserContext(); //object[] parameters = new object[] { stream, parserContext, null, false }; //object bamlRoot = LoadBamlMethod.Invoke(null, parameters); //return (T)bamlRoot; //For .net 4.0 var reader = new Baml2006Reader(stream); var writer = new XamlObjectWriter(reader.SchemaContext); while (reader.Read()) writer.WriteNode(reader); return (T)writer.Result; } 

And in order to combine resources from another assembly into the current assembly:

 private void LoadResources() { List<Stream> bamlStreams = GetBamlStreams(FullName); foreach (Stream stream in bamlStreams) { ResourceDictionary rd = LoadBaml<ResourceDictionary>(stream); Application.Current.Resources.MergedDictionaries.Add(rd) } } 

In this example, this work is very versatile for trimming, but you can optimize it to achieve your specific goal, if necessary. You can see the skinning library that uses this method here on github , with a few examples to demonstrate.

+7
source

You do not need to put your ResourceDictionary inside "App.xaml". If you have a UserControl or Window, you can reference your ResourceDictionary.

 <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyProjectName;component/BrushResources.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserContro.Resources> 
+2
source

Why not just use MergedDictionaries in your other build?

  <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/BrushesLib;Component/BrushResources.xaml" /> </ResourceDictionary.MergedDictionaries> 
+1
source

If you know a different assembly structure, use the code below: XAML Solution

  ResourceDictionary dictionary = new ResourceDictionary(); dictionary.Source = new Uri("pack://application:,,,/WpfControlLibrary1;Component/RD1.xaml", UriKind.Absolute); foreach (var item in dictionary.Values) { //operations } 

Conclusion: If we want to use the ResourceDictionary RD1.xaml project in the StackOverflowApp project.

Project Structure:

Project structure

Resource Dictionary

ResourceDictionary

Code output:

Output

C # Solution:

use this link.

+1
source

All Articles