簡體   English   中英

如何鏈接從磁盤外部加載的資源字典,不包含在項目或程序集中?

[英]How can I chain Resource Dictionaries that are externally loaded from disk, not included in project or assembly?

我在一個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>

所以我正在使用XamlReader.Load(...)加載這個BlackSkin.xaml

如果我把它工作正常:

Source="D:\Temp2\BaseSkin.xaml"/>

這當然是硬編碼的路徑。 我想提供一個相對路徑,而不是相對於正在運行的當前應用程序,但是當前正在加載的皮膚的相對路徑(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();
            }

也許只是刪除BlackSkin.xaml中的BaseSkin.xaml查找...也就是說從BaseSkin.xaml中刪除這段代碼?

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="{StaticResource baseSkin}"/> <!--D:\Temp2\BaseSkin.xaml" /-->
</ResourceDictionary.MergedDictionaries>

但是,如果我想在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>

這就是我對自定義擴展的看法,只是試着看看我是否可以在自定義擴展中使用硬編碼路徑。 我誤解了什么嗎? 我將離開這個例子: 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";
        }
    }
}

我認為您可以定義自己的類,繼承自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;
        }
    }
}

采用:

<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>
...

但是你仍然需要決定如何設置BaseDirectory屬性;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM