Laden...

[gelöst] Relativer Pfad zu einer DLL der ResourceDictionary Source

Erstellt von Potestas vor 10 Jahren Letzter Beitrag vor 10 Jahren 7.727 Views
P
Potestas Themenstarter:in
20 Beiträge seit 2007
vor 10 Jahren
[gelöst] Relativer Pfad zu einer DLL der ResourceDictionary Source

Hallo,

ich würde gern eine Assembly als ResourceDictionary einbinden, welches sich im Unterverzeichnis der Anwendung befindet.

Z.Bsp:

\Root\Main.exe
\Root\Resource\MyResource.dll

Die XAML wiederrum liegt in einem Unterverzeichnis der MyResource.dll

Solange die MyResource.dll im Root liegt geht das natürlich wunderbar mit

<ResourceDictionary Source="pack://application:,,,/MyResource;component/Images/ResImages.xaml"/>

Wenn ich die MyResource nun aber in ein Unterverzeichnis lege, kann ich darauf nicht verweisen. Bisher habe ich noch nichts dazu gefunden, dass ein solcher Fall vorgesehen ist.

<ResourceDictionary Source="pack://application:,,,/Resource/MyResource;component/Images/ResImages.xaml"/>

Ich hatte zunächst die Hoffnung es über die Authority siteoforigin zu Lösen, diese scheint aber nur direkte Resources (XAML/PNG/etc) verarbeiten zu können und keine Assembys.


<ResourceDictionary Source="pack://siteoforigin:,,,/Module/Resource/MyResource.dll;component/Images/ResImages.xaml"/>

Eventuell gibt es ja doch eine Möglichkeit, die ich Übersehen habe.

Vielen Dank schonmal

R
212 Beiträge seit 2012
vor 10 Jahren

du kannst mit "../" in der ordnerstruktur zurücknavigieren dh:


<ResourceDictionary Source="pack://application:,,,/MyResource;component/../../{AnderesProjekt}/ResImages.xaml"/>

P
Potestas Themenstarter:in
20 Beiträge seit 2007
vor 10 Jahren

Danke für deine Nachricht.
Soweit ich es aber verstehe, wird hinter "component" nur der Pfad innerhalb der Assembly definiert, nicht aber der Pfad zur Assembly ansich.

Ich möchte ja den Pfad zur MyResource definieren.

P
Potestas Themenstarter:in
20 Beiträge seit 2007
vor 10 Jahren

ich bin etwas überrascht, dass es hierzu scheinbar keine "einfache Lösung" gibt, bzw. das noch niemand gemacht hat.

Ich habe jetzt eine (mehr oder weniger zufriedenstellende) Lösung.

Ich habe ein abgeleitetes ResourceDictionary genommen und im Codebehind die relative Resource aufgelöst und mit Assembly.Load geladen. Anschließend kann Sie dann über den normale SourcePfad geladen werden.

<Res:RelativeResourceDictionary ComponentPath="/Images/ResImages.xaml" RelativeAssemblyPath="/Module/Resource/MyResource.dll" DesignTimePath="<vollqualifizier Pfad>\Module\Resource\MyResource.dll"/>

Sehr unschön ist der Umstand des vollqualifizierten Pfades während der DesignTime.

Ich hoffe daher dennoch auf einen Hinweis, Tipp wie es ggf. doch ohne umwege funktionieren könnte.

90 Beiträge seit 2009
vor 10 Jahren

Edit:
Oh, war wohl etwas zu langsam. Anscheinend hatten wir fast den selben Einfall. 👍


Servus Potestas,

wenn ich dich richtig verstehe dann möchtest Du den 'Component'-Bereich aus der URI dynamisch zur Laufzeit abändern, sodass dieser immer auf die aktuelle .dll abzielt?

Ich hatte nämlich eben dass selbe Problem und habe dieses mit einem selbst erstellten ResourceDictionary gelöst.
(Keine Ahnung ob man dieses Problem auch noch anders lösen könnte, mir ist auf die Schnelle kein besserer Weg eingefallen)

Mein ResourceDictionary:


    /// <summary>
    /// Repräsentiert ein ResourceDictionary welches Resources aus der aktuellen Bibliothek heranzieht
    /// </summary>
    public class ThemeResourceDictionary : ResourceDictionary
    {
        /// <summary>
        /// Ruft die URI zur Ressource aus der aktuellen Bibliothek ab oder legt diese fest
        /// </summary>
        public new Uri Source
        {
            get
            {
                return base.Source;
            }
            set
            {
                // Namen der aktuellen Assembly holen (ohne Dateiendung)
                var assemblyName = System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.ScopeName.TrimEnd(".dll");

                // URI so abändern sodass diese auf die aktuelle Assembly abzielt
                var componentName = String.Concat("/", assemblyName, ";component");
                base.Source = new Uri(String.Concat(componentName, value.ToString()), UriKind.RelativeOrAbsolute);
            }
        }
    }

Die Extensionsmethod 'Trim(..')':


    /// <summary>
    /// Beinhaltet Erweiterungsmethoden
    /// </summary>
    public class Extensions
    {
        /// <summary>
        /// Entfernt die Zeichenkette am Ende wenn vorhanden
        /// </summary>
        /// <param name="target">Textzeichenfolge welche manipuliert werden soll</param>
        /// <param name="trimString">Zeichenkette welche entfernt werden soll</param>
        /// <returns>Neue Textzeichenfolge</returns>
        public static string TrimEnd(this string target, string trimString)
        {
            var result = target;
            while (result.EndsWith(trimString))
            {
                result = result.Substring(0, result.Length - trimString.Length);
            }

            return result;
        }
    }

Und zum Schluss noch das ResourceDictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:controls="clr-namespace:NamespaceZumThemeResourceDictionary">

    <ResourceDictionary.MergedDictionaries>
        <controls:ThemeResourceDictionary Source="/Subfolder1/Subfolder2/File.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Hoffe geholfen zu haben.

Viele Grüße

Kumatin tanaki - Grabt den Klappstuhl aus!

P
Potestas Themenstarter:in
20 Beiträge seit 2007
vor 10 Jahren

Hallo scoKi!,

Vielen Dank für dein Beispiel!

Mein Problem ist, dass ich eine Resource laden möchte, welche sich nicht im Verzeichnis der Anwendung befindet, sondern in einem Unterverzeichnis.

Der Component-Bereich gibt den Pfad innerhalb der Assembly an. Ich brauche aber einen relativen Pfad zur Assembly.

Viele Grüße

P
660 Beiträge seit 2008
vor 10 Jahren

Hallo,

vllt. hilft dir das probing-Element weiter.

oder versuchtst du Styles/Bilder aus der Assembly zu laden?
dann kannst du den Pfad ja z.b. so angeben

 <ResourceDictionary ...> 
    <MergedDictionary ...>
        <ResourceDictionary Source="../Styles/MyStyle.xaml" />
    </MergedDictionary>
</ResourceDictionary>

oder im CodeBehind

var resourceDictionary = (ResourceDictionary)Application.LoadComponent(new Uri("../Styles/MyStyle.xaml", UriKind.Relative));
Program.Resources.MergedDictionaries.Add(resourceDictionary);

das "../" navigiert dabei eine Ebene höher. "../../" würde also zwei Ebenen höher navigieren

MfG
ProGamer*Der Sinn Des Lebens Ist Es, Den Sinn Des Lebens Zu Finden! *"Wenn Unrecht zu Recht wird dann wird Widerstand zur Pflicht." *"Ignorance simplifies ANY problem." *"Stoppt die Piraterie der Musikindustrie"

P
Potestas Themenstarter:in
20 Beiträge seit 2007
vor 10 Jahren

Danke ProGamer

der Tipp mit dem probing war super.


<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Module\Resource"/>
    </assemblyBinding>
  </runtime>

Trotz allem bin ich etwas enttäuscht über die fehlende Möglichkeit, dass gleich in der Source zu definieren. 🤔