あなたが求めているのは、アプリケーションで真のスキニングを提供するために必要な機能のコンポーネントです。別のアセンブリからリソースを取得するには、コンパイルされた XAML またはBAMLを他のアセンブリから読み取る必要があります。アセンブリから 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)
}
}
この例では、スキニングの目的で非常に一般的な方法で作業を行いますが、必要に応じて、これを簡素化して特定の目標を達成できます。このメソッドを使用するスキニング ライブラリは、こちらの githubで確認でき、いくつかの例を示しています。