c# - 从其他程序集实例化 ResourceDictionary xaml

标签 c# wpf xaml resourcedictionary

我在 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 实例?

最佳答案

您要问的是在应用程序中提供真实皮肤所必需的功能组件。从单独的程序集中获取资源涉及读取已编译的 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)
    } 
} 

此示例以一种非常通用的方式完成工作以用于蒙皮目的,但您可以简化此操作以在必要时实现您的特定目标。你可以看到一个使用这种方法的换肤库here on github ,用几个例子来证明。

关于c# - 从其他程序集实例化 ResourceDictionary xaml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15548769/

相关文章:

c# - 如何根据方法返回启用/禁用 WPF 按钮

c# - 相当于Xamarin forms中Div的 "float:left"

wpf - 如何以编程方式将新元素停靠到 DockPanel

c# - 获取 WPF 列表框中所选项目的文本

c# - WPF 按钮背景 mouseenter 和离开不按预期工作

c# - 如何针对特定条件扩展 WPF 窗口?

c# - 什么是 C++ 的 std::bitset 的 C# 等价物

c# - 异步更新文本框

c# - 等待 BackgoundWorker.DoWork() 完成

c# - 我的 Controller 对象是否会为每个请求实例化并从内存中销毁?