5

色とブラシを含む WPF クラス ライブラリで、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ですか?

4

4 に答える 4

8

あなたが求めているのは、アプリケーションで真のスキニングを提供するために必要な機能のコンポーネントです。別のアセンブリからリソースを取得するには、コンパイルされた 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で確認でき、いくつかの例を示しています。

于 2013-03-21T14:57:13.927 に答える
1

他の構造がわかっている場合は、assembly以下のコードを使用してください: XAML ソリューション

 ResourceDictionary dictionary = new ResourceDictionary();
 dictionary.Source = new Uri("pack://application:,,,/WpfControlLibrary1;Component/RD1.xaml", UriKind.Absolute);
 foreach (var item in dictionary.Values)
 {
    //operations
 }

出力:ResourceDictionary RD1.xaml ProjectWpfControlLibrary1 をプロジェクトに使用する場合StackOverflowApp

プロジェクトの構造:

プロジェクトの構造

リソース ディクショナリ

リソース辞書

コード出力:

出力

c# ソリューション:

このリンクを使用してください。

于 2016-04-15T12:41:35.423 に答える
1

他のアセンブリで単に MergedDictionaries を使用しないのはなぜですか?

 <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/BrushesLib;Component/BrushResources.xaml" />
</ResourceDictionary.MergedDictionaries>
于 2013-03-21T13:42:15.030 に答える