Styles zur Laufzeit nachladen greift nicht
-
Hallo,
frohes Neues zunächst mal euch allen
Ich habe ein UserControl <Label> programmiert, welches aus zwei <TextBlock> besteht (Name und Wert, ganz simpel). Die XAML Datei sieht wie folgt aus:
<UserControl x:Class="DotNet.WpfControls.Base.Label" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DotNet.WpfControls.Base" mc:Ignorable="d"> <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resources/Styles/DefaultStyles.xaml"/> <ResourceDictionary Source="Resources/Styles/Label.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Name="LabelColumn" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> </Grid.RowDefinitions> <TextBlock Grid.Column="0" Grid.Row="0" Margin="4, 2, 4, 2" Name="InternalName" Style="{StaticResource LabelName}" Text="Name" /> <TextBlock Grid.Column="1" Grid.Row="0" Margin="4, 2, 4, 2" Name="InternalValue" Style="{StaticResource LabelValue}" Text="Value" /> </Grid> </UserControl>
In der oberen Hälfte referenziere ich zwei <ResourceDictionary>, diese sehen wie folgt aus:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- Default TextBlock --> <Style x:Key="DefaultTextBlock" TargetType="TextBlock"> <Setter Property="TextWrapping" Value="NoWrap" /> <Setter Property="TextTrimming" Value="None" /> </Style> </ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="DefaultStyles.xaml" /> </ResourceDictionary.MergedDictionaries> <!-- Style for the name text block --> <Style BasedOn="{StaticResource DefaultTextBlock}" x:Key="LabelName" TargetType="TextBlock"> <Setter Property="TextDecorations" Value="{x:Null}" /> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="TextDecorations" Value="Underline" /> </Trigger> </Style.Triggers> </Style> <!-- Style for the value text block --> <Style BasedOn="{StaticResource DefaultTextBlock}" x:Key="LabelValue" TargetType="TextBlock"> </Style> </ResourceDictionary>
Wenn ich das Programm aus VisualStudio heraus starte, sieht alles gut aus und es funktioniert auch alles. Nun möchte ich aber die <Styles> in der <Auslieferungsversion> im Verzeichnis <.\resources\styles*.xaml> ablegen, damit der Anwender meines Programms die Möglichkeit hat, die Stile individuell anzupassen.
In der App.cs lade ich wie folgt:
private void LoadStyles() { var currentDirectory = Environment.CurrentDirectory; var styles = new List<string>() { "DefaultStyles.xaml", "Label.xaml" }; foreach (var item in styles) { var pathName = Path.Combine(currentDirectory, ResourcesPathName, StylesPathName, item); var resourceDictionary = new ResourceDictionary { Source = new Uri(pathName) }; this.Resources.MergedDictionaries.Add(resourceDictionary); } }
Das Laden ansich führt zu keinem Laufzeitfehler, die Dateien werden gefunden und geladen. Wenn ich aber die Datei <DefaultStyles.xaml> anpasse und z.B. die Vordergrundfarbe für das <TextBlock> setze, greift diese Änderung nicht:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- Default TextBlock --> <Style x:Key="DefaultTextBlock" TargetType="TextBlock"> <Setter Property="Foreground" Value="Red" /> <Setter Property="TextWrapping" Value="NoWrap" /> <Setter Property="TextTrimming" Value="None" /> </Style> </ResourceDictionary>
Weiß jemand, was ich wo falsch mache?
Vielen Dank im Voraus
VG Torsten
-
Das wird m.E. daran liegen, daß die beiden Ressourcen schon im
MergedDictionaries
vorhanden sind (und perAdd
fügst du diese ja hinten dran).
Entweder versuchen diese zu ersetzen bzw. vorne hinzuzufügen.Außerdem:
WennLoadStyles
eine Methode deinerApp
-Klasse (und nicht derLabel
-Klasse) ist, so bezieht sichthis.Resources
auf die Ressourcen derApp
und nicht derLabel
-Instanz, s.a. ResourceDictionary:Verwendung von ResourceDictionary-Elementen
Der ResourceDictionary-Typ wird als Wert der beiden Eigenschaften
FrameworkElement.Resources
undApplication.Resources
verwendet.
-
Hallo,
gute Hinweise, danke. Ich schaue mir das mal an.
VG Torsten
-
N' Abend,
nun habe ich es geschafft, das Problem ist vermutlich zweierlei.
Erstens, einige Zeilen auskommentieren:
<UserControl x:Class="DotNet.WpfControls.Base.Label" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DotNet.WpfControls.Base" mc:Ignorable="d"> <!--<UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resources/Styles/DefaultStyles.xaml"/> <ResourceDictionary Source="Resources/Styles/Label.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources>--> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Name="LabelColumn" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> </Grid.RowDefinitions> <TextBlock Grid.Column="0" Grid.Row="0" Margin="4, 2, 4, 2" Name="InternalName" Style="{DynamicResource LabelName}" Text="Name" /> <TextBlock Grid.Column="1" Grid.Row="0" Margin="4, 2, 4, 2" Name="InternalValue" Style="{DynamicResource LabelValue}" Text="Value" /> </Grid> </UserControl>
Zweitens, die Lademethode leicht anpassen:
private void LoadStyles() { var currentDirectory = Environment.CurrentDirectory; var styles = new List<string>() { "DefaultStyles.xaml", "Label.xaml" }; App.Current.Resources.Clear(); foreach (var item in styles) { var pathName = Path.Combine(currentDirectory, ResourcesPathName, StylesPathName, item); var resourceDictionary = new ResourceDictionary { Source = new Uri(pathName) }; App.Current.Resources.MergedDictionaries.Add(resourceDictionary); } }
Und man muss <DynamicResource> anstatt von <StaticResource> verwenden.
VG Torsten