我在包含颜色和画笔的WPF类库中定义了一个Reource Dictionary,名为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>
我想在另一个程序集的代码中使用一些Brushes,它引用了这个库项目。如何获得ResourceDictionary
的实例?
答案 0 :(得分:8)
您所询问的是在应用程序中提供真正皮肤所需功能的组件。从单独的程序集中获取资源涉及从另一个程序集中读取已编译的XAML或BAML。这是我在skinning库中使用的方法,用于从程序集中检索BAML:
//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转换为特定资源,请执行以下操作:
//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;
}
为了将其他程序集中的资源合并到当前程序集中:
private void LoadResources()
{
List<Stream> bamlStreams = GetBamlStreams(FullName);
foreach (Stream stream in bamlStreams)
{
ResourceDictionary rd = LoadBaml<ResourceDictionary>(stream);
Application.Current.Resources.MergedDictionaries.Add(rd)
}
}
此示例以非常通用的方式为蒙皮目的进行工作,但您可以简化此操作以在必要时实现您的特定目标。您可以看到使用此方法here on github的皮肤库,并举几个示例进行演示。
答案 1 :(得分:2)
您不必将您的ResourceDictionary放在“App.xaml”中。如果您有UserControl或Window,则可以链接到ResourceDictionary。
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyProjectName;component/BrushResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserContro.Resources>
答案 2 :(得分:1)
为什么不在其他程序集中使用MergedDictionaries?
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/BrushesLib;Component/BrushResources.xaml" />
</ResourceDictionary.MergedDictionaries>
答案 3 :(得分:1)
如果您知道其他file
结构,请使用以下代码:
XAML解决方案
assembly
输出:如果我们想将项目 ResourceDictionary dictionary = new ResourceDictionary();
dictionary.Source = new Uri("pack://application:,,,/WpfControlLibrary1;Component/RD1.xaml", UriKind.Absolute);
foreach (var item in dictionary.Values)
{
//operations
}
的{{1}} ResourceDictionary
用于RD1.xaml
项目。
项目结构:
资源字典
代码输出:
c#解决方案: