从其他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#解决方案:
使用此链接。