Laden...

Resource Dictionary: StaticResource im Setter eines Styles einsetzen

Erstellt von Davaaron vor 4 Jahren Letzter Beitrag vor 4 Jahren 2.919 Views
D
Davaaron Themenstarter:in
106 Beiträge seit 2016
vor 4 Jahren
Resource Dictionary: StaticResource im Setter eines Styles einsetzen

Hi,

ist es möglich, dass ich eine statische Resource, z.B. Color, als Wert für einen Setter innerhalb eines Styles verwende? Ich habe es bereits auf dem "herkömmlichen" Weg versucht, aber ohne Erfolg. Im Editor konnte ich das Ergebnis kurz sehen und es sah gut aus. Nach ein paar Sekunden bekomme ich eine Fehlermeldung, dass die statische Ressource eine Exception ausgelöst hat, weil sie nicht gefunden werden kann.
So verwende ich den Style quasi in der Resource Dictionary:


<Color x:Key="TxtDarkColor">#BEBEBE</Color>


    <Style x:Key="Test" TargetType="Window">
        <Setter Property="Background" Value="{TxtDarkColor}"></Setter>
    </Style>


Und so binde ich sie dann ein:


<Button Style={StaticResource Test}/>

Wie macht ihr so was?

5.657 Beiträge seit 2006
vor 4 Jahren
<Setter Property="Background" Value="{StaticResource TxtDarkColor}"></Setter>

und

<Button Style="{StaticResource Test}"/>

mit Anführungszeichen!

Und

<Style x:Key="Test" TargetType="Button">

mit dem richtigen TargetType.

Weeks of programming can save you hours of planning

187 Beiträge seit 2009
vor 4 Jahren

Hallo,
die BackgroundProperty muss vom Typ SolidColorBrush sein!
Außerdem stimmt an mehreren Stellen die Syntax nicht ganz.


    <Color x:Key="TxtDarkColor">#ebebeb</Color>
    <SolidColorBrush x:Key="BackgroundBrush" Color="{StaticResource TxtDarkColor}" />
    
    <Style x:Key="Test" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="{StaticResource BackgroundBrush}"></Setter>
    </Style>


        <Button Style="{StaticResource Test}"/>

D
Davaaron Themenstarter:in
106 Beiträge seit 2016
vor 4 Jahren

Ups, die Anführungszeichen habe ich beim Abtippen vergessen. Und ich hatte das falsche Template gepostet..
Das mit dem SolidColorBrush war eine gute Idee, jetzt habe ich wieder IntelliSense wenn es um die StaticResource Auswahl geht.
Was allerdings noch nicht so recht funktioniert ist das Einbinden des Styles per x:Key.

So sieht der aktuelle Style des Buttons aus:


<Style x:Key="CloseableBtn" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="BorderThickness" Value="0"></Setter>
            <Setter Property="Background" Value="Transparent"></Setter>
            <Setter Property="BorderBrush" Value="Transparent"></Setter>
            <Setter Property="Padding" Value="0,0,3,0"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Selected}" Value="True">
                    <Setter Property="Background" Value="Transparent"></Setter>
                </DataTrigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Transparent"></Setter>
                    <Setter Property="Foreground" Value="LightGoldenrodYellow"></Setter>
                    <Setter Property="BorderThickness" Value="1"></Setter>
                </Trigger>
                <DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
                    <Setter Property="Visibility" Value="Visible"></Setter>
                    <Setter Property="Foreground" Value="DarkOrange"></Setter>
                    <Setter Property="BorderBrush" Value="DarkOrange"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>

Das Resource-Dictionary lade ich per Code-Behind, da es mit XAML irgendwie nicht laden wollte..
Und so verwende ich dann den Key in meinem Template:


  <DataTemplate DataType="{x:Type vms:TabItemViewModel}" >
            <Grid MinWidth="75">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"></ColumnDefinition>
                    <ColumnDefinition Width="Auto"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock VerticalAlignment="Center" Text="{Binding Header}"/>
                <Button Style="{StaticResource CloseableBtn}" Content="X" Grid.Column="1" Focusable="False"
                        FontFamily="Courier" FontSize="9" FontWeight="Bold"  Margin="0,1,0,0" Padding="0" 
                         Width="16" Height="16" 
                            Command="{Binding CloseCmd}"/>
            </Grid>
        </DataTemplate>

Die Fehlermeldung lautet:

Exception: Die Ressource mit dem Namen "CloseableBtn" kann nicht gefunden werden. Bei Ressourcennamen wird die Groß- und Kleinschreibung berücksichtigt.

Was mich ebenfalls etwas stört, ist, dass die Styles nicht mehr im Designer angwendet werden. Somit sehen alle Controls gleich aus.. wenn ich aber den Style auskommentiere, dann sind in der laufenden Anwendung die Styles angewandt worden. Entferne ich dann während der Laufzeit die Kommentare im .xaml, dann werden auch die Styles mit dem x:Key angezeigt. Beende ich die App und starte sie neu, bekomme ich oben genannte Fehlermeldung.

Zu beachten ist dabei auch, dass ich NET Core 3 verwende.. könnte sich wohl auch um einen Bug handeln, oder? Müsste ich mal mit dem Framework gegen testen, oder fällt euch dazu was ein?

5.657 Beiträge seit 2006
vor 4 Jahren

da es mit XAML irgendwie nicht laden wollte..

könnte sich wohl auch um einen Bug handeln, oder?

Angesichts deines bisher geposteten Codes würde ich erstmal nicht von einem Fehler bei Microsoft ausgehen. Aber mit "wollte irgendwie nicht" können wir halt auch nicht viel anfangen, um dir weiterzuhelfen.

Siehe auch [Hinweis] Wie poste ich richtig?, Punkt 5

Weeks of programming can save you hours of planning

D
Davaaron Themenstarter:in
106 Beiträge seit 2016
vor 4 Jahren

Aktuell lade ich das Resource Dictionary so rein (Code-Behind in MainWindow, nach InitalizeComponent):


var s= new Uri("pack://application:,,,/Styles/ButtonStyle.xaml", UriKind.RelativeOrAbsolute);
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = s});

Weil folgende Lösungen nicht funktioniert haben (innerhalb App.xaml):


<ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Styles/ButtonStyle.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

oder aber auch auch


<ResourceDictionary x:Key="T" Source="Styles/ButtonStyle.xaml">

Es gab dazu keine Fehlermeldung und nichts, aber die Styles wurden eben nicht geladen.

Mein Problem ist aber nun nicht, dass das Resource Dictionary nicht geladen wird. Das Problem ist eher, dass der Key (CloseableBtn) aus dem Resource Dictionary nicht gefunden wird. Und da müsste es doch eigentlich egal sein, ob ich das Resource Dictionary nun per XAML oder Code-behind lade, oder nicht?

D
Davaaron Themenstarter:in
106 Beiträge seit 2016
vor 4 Jahren

Ne, das ist es leider auch nicht. Hab auch den Namen per C&P hinter "StaticResource" eingefügt. Hab aber aus "Closeable" mal "Closable" gemacht, der Genauigkeit wegen.

Aber ich hab es nun... in der App.xaml hatte ich all meine DataTemplates (die Styles in der ButtonStyle.xaml) und hatte das ResourceDictionary per Code aber erst im MainWindowViewModel geladen. Daher konnte das xaml tatsächlich nicht gefunden werden..
Da ich kein AppViewModel haben will, probierte ich nochmal die XAML-Variante aus und die Lösung ist denkbar einfach: Man kann kein ResourceDictionary laden und gleichzeitig noch DataTemplates innerhalb des Resources-Tag deklarieren. Also sind die DataTemplates jetzt ebenfalls in die XAML gewandert und zwar ganz nach unten, so dass nun auch die per Key definierten Styles zur Verfügung stehen. In der App.xaml lade ich die Styles dann so:


<Application.Resources>
        <ResourceDictionary Source="pack://application:,,,/Styles/ButtonStyle.xaml"/>
        
    </Application.Resources>

1.040 Beiträge seit 2007
vor 4 Jahren

Man kann kein ResourceDictionary laden und gleichzeitig noch DataTemplates innerhalb des Resources-Tag deklarieren.

Doch, kann man.


<xyz.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Styles/ButtonStyle.xaml"/>
        </ResourceDictionary.MergedDictionaries>

        <!-- weitere Styles, Brushes, DataTemplates etc. definieren -->
    </ResourceDictionary>        
</xyz.Resources>

Kannst du mal bitte kurz erzählen, wo du die DataTemplates vorher definiert hast?

D
Davaaron Themenstarter:in
106 Beiträge seit 2016
vor 4 Jahren

Stimmt, so geht's. Hatte vorher kein MergedDictionaries benutzt sondern einfach ein ResourceDictionary und auf der gleichen Ebene die DataTemplates geladen. Da kam dann auch die Fehlermeldung "The property Resources can only be set once.".

Mein erster Versuch war dieser hier:


 <Application.Resources>
        <ResourceDictionary Source="pack://application:,,,/Styles/ButtonStyle.xaml"/>
        <DataTemplate DataType="{x:Type vms:MainWindowViewModel}"></DataTemplate>
        <!-- weitere DataTemplates -->
</Application.Resources>

Das meinte ich quasi mit

Man kann kein ResourceDictionary laden und gleichzeitig noch DataTemplates innerhalb des Resources-Tag deklarieren.

Mir war schlichtweg nicht klar und es hat etwas gedauert um zu begreifen, dass "Application.Resources" neben "ResourceDictionary" keine weiteren Subelemente haben darf, wenn man sich dazu entscheidet, eben ein ResourceDictionary zu verwenden. Man kann aber, wie du schon gezeigt hast, beides kombinieren, wenn man ein MergedDictionary verwendet.