从实例化大会其他ResourceDictionary中的XAML [英] Instantiate ResourceDictionary xaml from other Assembly
问题描述
我在含颜色和画笔,称为BrushResources.xaml一个WPF类库中定义的Reource字典
I have defined a Reource Dictionary in a 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>
我想用一些刷的代码从另一个组件,它引用该库项目。如何获得 ResourceDictionary中
的一个实例呢?
推荐答案
什么你再问的是所必需的功能的组件,以提供真正的换肤在应用程序中。获取资源从一个单独的程序包括从其他装配读编译XAML,或 BAML 。下面是我在一个剥皮库使用的方法从一个组件检索BAML:
What you're asking is a component of the functionality necessary to provide true skinning in an application. Getting resources from a separate assembly involves reading the compiled XAML, or BAML from the other assembly. Here is a method I use in a skinning library to retrieve the BAML from an 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;
}
随后,向BAML对特定资源转换,你就以下内容:
Then, to convert the 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 merge the resources from the other 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)
}
}
这例子做的工作在剥皮的目的一个非常通用的方式,但你可以简化这一如有必要,以实现自己的特定目标。你可以看到,使用此方法这里在github 剥皮库,用几个例子来演示。
This example does the work in a very generic manner for skinning purposes, but you can streamline this to accomplish your specific goal if necessary. You can see a skinning library that uses this method here on github, with a few examples to demonstrate.
这篇关于从实例化大会其他ResourceDictionary中的XAML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!