从其他Assembly实例化ResourceDictionary xaml

我在包含颜色和画笔的WPF类库中定义了一个Reource Dictionary,名为BrushResources.xaml。

   

我想在另一个程序集的代码中使用一些Brushes,它引用了这个库项目。 如何获得它的ResourceDictionary实例?

您要问的是在应用程序中提供真正皮肤所需的function组件。 从单独的程序集中获取资源涉及从另一个程序集中读取已编译的XAML或BAML 。 这是我在skinning库中使用的方法,用于从程序集中检索BAML:

 //Relevant Namespaces: //using System.Windows.Baml2006; //using System.Xaml; public static List GetBamlStreams(AssemblyName skinAssemblyName) { List bamlStreams = new List(); 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; } 

然后,要将BAML转换为特定资源,请执行以下操作:

 //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(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; } 

并且为了将来自其他程序集的资源合并到当前程序集中:

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

此示例以非常通用的方式为蒙皮目的进行工作,但您可以简化此操作以在必要时实现您的特定目标。 你可以在github上看到一个使用这个方法的皮肤库, 并举几个例子来演示。

您不必将ResourceDictionary放在“App.xaml”中。 如果您有UserControl或Window,则可以链接到ResourceDictionary。

        

为什么不简单地在你的其他程序集中使用MergedDictionaries?

     

如果您知道其他assembly结构,请使用以下代码: 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 } 

输出:如果我们想将Project WpfControlLibrary1 ResourceDictionary WpfControlLibrary1用于StackOverflowApp项目。

项目结构:

项目结构

资源字典

资源字典

代码输出:

产量

c#解决方案:

使用此链接。