如何链接从磁盘外部加载的资源字典,不包含在项目或程序集中?

Set*_*den 5 .net c# wpf xaml resourcedictionary

我在一个xaml文件中有一个ResourceDictionary,它表示我的硬盘驱动器上某个随机文件夹中的一个皮肤.说D:\ Temp2\BlackSkin.xaml.

我已正确设置权限以提供完全访问权限,因此不是问题.

这个ResourceDictionary BlackSkin.xaml像这样引用了一个BaseSkin.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="{D:\Temp2\BaseSkin.xaml">
</ResourceDictionary.MergedDictionaries>
Run Code Online (Sandbox Code Playgroud)

所以我正在使用XamlReader.Load(...)加载这个BlackSkin.xaml

如果我把它工作正常:

Source="D:\Temp2\BaseSkin.xaml"/>
Run Code Online (Sandbox Code Playgroud)

这当然是硬编码的路径.我想提供一个相对路径,而不是相对于正在运行的当前应用程序,但是当前正在加载的皮肤的相对路径(BlackSkin.xaml)...又名"D:\ Temp2\BaseSkin.xaml".. .or ...如果您只是"BaseSkin.xaml",因为它们位于同一个文件夹中,该文件夹与应用程序的文件夹不同.

我是否需要定义自定义标记扩展才能执行此操作?如果是这样,我会把它放在我的项目中?只需创建一个名为"Extensions"的文件夹并创建一些随机的.cs文件并在那里实现它?调用XamlReader.Load(...)时会调用这样的自定义标记扩展吗?

然后,我需要将此自定义标记扩展绑定到程序中,以从我的应用程序中的某个设置或配置文件获取完全限定的路径,并将路径作为ProvideValue函数的一部分返回?

有没有其他方法可以做到这一点?

比如我在这里调用XamlReader.Load(fileStream):

public void ApplySkin(string fileName, string baseSkinFileName)
    {
        if (File.Exists(baseSkinFileName))
        {
            ResourceDictionary baseSkinDictionary = null;
            using (FileStream baseSkinStream = new FileStream(baseSkinFileName, FileMode.Open))
            {
                //Read in the BaseSkin ResourceDictionary File so we can merge them manually!
                baseSkinDictionary = (ResourceDictionary)XamlReader.Load(baseSkinStream);
                baseSkinStream.Close();
            }
            using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
            {
                // Read in ResourceDictionary File
                ResourceDictionary skinDictionary = (ResourceDictionary)XamlReader.Load(fileStream);
                skinDictionary.MergedDictionaries.Add(baseSkinDictionary);
                // Clear any previous dictionaries loaded
                Resources.MergedDictionaries.Clear();
                // Add in newly loaded Resource Dictionary
                Resources.MergedDictionaries.Add(skinDictionary);
                fileStream.Close();
            }
Run Code Online (Sandbox Code Playgroud)

也许只是删除BlackSkin.xaml中的BaseSkin.xaml查找...也就是说从BaseSkin.xaml中删除这段代码?

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="{StaticResource baseSkin}"/> <!--D:\Temp2\BaseSkin.xaml" /-->
</ResourceDictionary.MergedDictionaries>
Run Code Online (Sandbox Code Playgroud)

但是,如果我想在BlackSkin.xaml中加载其他资源,如图像或其他任何东西,问题就变成了什么?所以我猜上面的内容真的只适用于像这样的通用一次性使用情况,但我真正想要的是一个通用的解决方案,可以将各种不同的资源链接到一个ResourceDictionary,这是一个位于a的外部文件磁盘上的随机文件夹,以及可能与也可能不与原始xaml资源Dictionary文件位于同一位置的资源.

这让我回到了Custom Markup Extensions问题.

编辑:

好吧,我确实尝试创建一个自定义标记扩展,但它抛出一个XamlParseException,我想因为它不知道clr-namespace是什么,再次因为它不在任何程序集或任何那种性质可以与之相关的正在运行的程序.

所以这就是我现在拥有的Xaml,也许我完全错了,或者我可能完全走错了路?...

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:base="clr-namespace:TimersXP.Extensions">
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="{base:BaseSkinPath}"/> <!--D:\Temp2\BaseSkin.xaml" /-->
</ResourceDictionary.MergedDictionaries>
Run Code Online (Sandbox Code Playgroud)

这就是我对自定义扩展的看法,只是试着看看我是否可以在自定义扩展中使用硬编码路径.我误解了什么吗?我将离开这个例子:http: //tech.pro/tutorial/883/wpf-tutorial-fun-with-markup-extensions

using System;
using System.Windows.Markup;

namespace TimersXP.Extensions
{
    class BaseSkin : MarkupExtension
    {
        /// <summary>Gets the base skin file path.</summary>
        /// <value>The base skin.</value>
        public string BaseSkinPath
        {
            get { return "D:\\Temp2\\BaseSkin.xaml"; }
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return "D:\\Temp2\\BaseSkin.xaml";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

vla*_*yev 2

我认为您可以定义自己的类,继承自 ResourceDictionary,并在 MergedDictionaries 部分中使用它。

定义:

public class SkinResourceDictionary : ResourceDictionary {
    public static string BaseDirectory { get; set; }

    public new Uri Source {
        get {
            return base.Source;
        }
        set {
            base.Source = BaseDirectory + value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1">
<ResourceDictionary.MergedDictionaries>
    <local:SkinResourceDictionary Source="\BaseSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
...
Run Code Online (Sandbox Code Playgroud)

但您仍然需要决定如何设置 BaseDirectory 属性;