Resourcen-Prinzipien
In Wpf kann man auf allen Ebenen (Scopes) ResourceDictionaries anlegen, und da je beliebige Objekte reinwerfen.
Um die Objekte wiederzufinden ist natürlich sowas wie ein Schlüssel erforderlich.
Für beliebige Objekte ist ein
Derselbe Schlüssel darf auf verschiedenen Ebenen verwendet werden - Auflösungs-Regel ist: Ein Element beginnt die Resourcen-Suche anhand eines Keys im lokalen Scope, und steigt immer höher bis auf Application-Ebene. Jedoch bei der ersten Key-Übereinstimmung ist die Suche beendet, und die zum Key gehörige Resource wird genommen.
Dieses Prinzip heisst übrigens "Abschattierung", und kommt auch in anneren Bereichen der Programmierung so ähnlich vor - ja sogar in der realen Welt - (etwa wenn Verträge gesetzliche Default-Bestimmungen re-definieren - Kündigungsfristen etc).
Ein weiteres Konzept ist: Manche Klassen haben auch eine eingebauten Schlüssel-Property, etwa
Scope-Demo
Um obiges zu demonstrieren habich klein Beispiel gebastelt - in 4 tw. verschachtelten DockPanels liegen 6 numerierte Label mit "gestylten" Rahmen-Dicke und Rahmen-/Text-Farben:
Xaml dazu:
Hier kommen 4 Styles zum Einsatz - letztendlich alle basierend auf dem ersten, "outerStyle", angelegt inne Window-Resourcen - hier der oberste Scope. Das ist gleich so einer ohne explizitem Key - sodass sein TargetType (
Auf diesem "outerStyle" basiert ein Keyed Style (Zeile
Hingegen der eigene, explizite
Da er keyed ist, kommt dieser Style nur zur Anwendung, wenn ausdrücklich auf ihn verwiesen wird - wie in Zeile
Im zweiten eingeschachtelten DockPanel findet sich der "middleStyle", auch basierend auf "outerStyle" - BorderBrush-modifiziert -
Also Label
Label
Im innersten DockPanel ist noch ein Style - "innerStyle", der denselben BasedOn-Key verwendet wie die vorherigen beiden Styles. Aber dieser addressiert nun den "middleStyle", welcher "outerStyle" an dieser Stelle ja abschattiert.
Daher "erbt" Label
Label
Die SystemColors-Klasse
So - also das mitte Scopes, Explizit-/ Auto-Keys, und die Style-Selbstanwendung bei Auto-Keys muss verstanden sein fürs Folgende.
Ich hab mich heuer mit der statischen Klasse
Wie gesagt: von derlei Farb-Zwecken gibts noch 31 mehr, etwa
"HighlightText": Selection-Schriftfarbe | "Control": Control-Hintergrund | "ControlText": C-Vordergrund | ...
Zu jedem dieser Zwecke fahren inne
Warum?
Weil in Wpf auch die Systemfarben einstellbar sind.
Also ein gehighlightetes
Wenn nichts anneres festgelegt ist.
Ich kann ja auch ein eigenes
Ätsch! - wenn nun ein
Man kann also mit wenigen Zeilen ganze Farb-Themes redefinieren, wenn man das toll findet. Anwendungsweit, aber auch jeder engere Scope: einzelne Fenster, Panels, wie wolle.
Oder man bastelt einen Style speziell für Listboxen:
So - meine Listboxen highlighten jetzt in Khaki, unter Beibehaltung der Textfarbe. Findich viel angenehmer als das Standard-Highlighting mit weissem Text auf DunkelBlau.
Ich hab diesen Style per Scope Super-Hoch aufgehängt - höher noch als Application-Ebene.
Nämlich in meine Wpf-Helpers hab ich ihn in ein ResourceDichtionary gemacht, und alle meine Wpf-Anwendungen inkludieren dieses, zB so:
Zeile #13 ist die Include-Anweisung - die Pfad-Angabe ist ein bischen krank - das ist ein
Mir reicht erstmal zu wissen, dass
Sample-Application
Inne Sample-Application hab ich ausserdem noch was anneres eingebunden, nämlich ein Resource-Dictionary, mit dem man jeden einzelnen FarbZweck auf "Red" umstellen kann. Und dazu habich eine Listbox gebastelt, um die ResourceKeys auszuwählen. Und ein Test-Control, wo man dann sieht, welcher Teil der Controls bei welchem ResourceKey rot wird.
Das Bildle zeigt, wie der HighlightBrushKey des selektierten ListboxItems Hintergrund errötet.
Die Sample-App enthält auch meine Helpers - also nicht erschrecken über die grosse Code-Menge - die eigentliche Haupt-Assembly ist sehr überschaubar.
In Wpf kann man auf allen Ebenen (Scopes) ResourceDictionaries anlegen, und da je beliebige Objekte reinwerfen.
Um die Objekte wiederzufinden ist natürlich sowas wie ein Schlüssel erforderlich.
Für beliebige Objekte ist ein
x:Key [Schlüssel]
anzugeben, und der Schlüssel kann ebenfalls ganz beliebig sein.Derselbe Schlüssel darf auf verschiedenen Ebenen verwendet werden - Auflösungs-Regel ist: Ein Element beginnt die Resourcen-Suche anhand eines Keys im lokalen Scope, und steigt immer höher bis auf Application-Ebene. Jedoch bei der ersten Key-Übereinstimmung ist die Suche beendet, und die zum Key gehörige Resource wird genommen.
Dieses Prinzip heisst übrigens "Abschattierung", und kommt auch in anneren Bereichen der Programmierung so ähnlich vor - ja sogar in der realen Welt - (etwa wenn Verträge gesetzliche Default-Bestimmungen re-definieren - Kündigungsfristen etc).
Ein weiteres Konzept ist: Manche Klassen haben auch eine eingebauten Schlüssel-Property, etwa
Style.TargetType
oder DataTemplate.DataType
oder ControlTemplate.TargetType
etc - man sieht: als eingebauter Schlüssel wird gern ein System.Type
verwendet. Das ist dann Bestandteil eines Mechanismus der "Selbstanwendung", über den der Style oder das Template (oder sonstwas) per default sich selbst auf Objekte des angegebenen Typs anwendet, solange das Objekt im Scope des ResourceDictionaries liegt, und im Xaml nix anderes angegeben ist.Scope-Demo
Um obiges zu demonstrieren habich klein Beispiel gebastelt - in 4 tw. verschachtelten DockPanels liegen 6 numerierte Label mit "gestylten" Rahmen-Dicke und Rahmen-/Text-Farben:
Xaml dazu:
XML-Quellcode
- <Window x:Class="ScopeDemo"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="ScopeDemo" Height="400" Width="300" Left="0" Top="0" Background="#FFF7F766">
- <FrameworkElement.Resources>
- <Style TargetType="{x:Type Label}"> <!--outerStyle-->
- <Setter Property="BorderBrush" Value="Black"/>
- <Setter Property="BorderThickness" Value="13"/>
- <Setter Property="Margin" Value="10"/>
- <Setter Property="Padding" Value="15"/>
- <Setter Property="FontSize" Value="15"/>
- <Setter Property="FontWeight" Value="Bold"/>
- <Setter Property="Foreground" Value="#FFF71010"/>
- </Style>
- <Style x:Key="keyedStyle" BasedOn="{StaticResource {x:Type Label}}" TargetType="Label"> <!--keyedStyle-->
- <Setter Property="BorderThickness" Value="5"/>
- </Style>
- </FrameworkElement.Resources>
- <DockPanel>
- <Label DockPanel.Dock="Top">1</Label>
- <DockPanel>
- <Label>2</Label>
- <DockPanel>
- <FrameworkElement.Resources>
- <Style BasedOn="{StaticResource {x:Type Label}}" TargetType="Label"> <!--middleStyle-->
- <Setter Property="BorderBrush" Value="Blue"/>
- </Style>
- </FrameworkElement.Resources>
- <Label DockPanel.Dock="Top">3</Label>
- <Label>4</Label>
- <DockPanel>
- <FrameworkElement.Resources>
- <Style BasedOn="{StaticResource {x:Type Label}}" TargetType="Label"> <!--innerStyle-->
- <Setter Property="Foreground" Value="Blue"/>
- </Style>
- </FrameworkElement.Resources>
- <Label DockPanel.Dock="Top">5</Label>
- <Label Style="{StaticResource keyedStyle}">6</Label>
- </DockPanel>
- </DockPanel>
- </DockPanel>
- </DockPanel>
- </Window>
Label
) auch sein Key ist, und ausserdem alle Labels in seim Scope defaultmässig diesen Style auf sich anwenden.Auf diesem "outerStyle" basiert ein Keyed Style (Zeile
#15
), mit modifizierter BorderThickness. Beachte, wie die BasedOn-Property den "outerStyle" referenziert: Als Referenz-Key ist der Datentyp Label
angegeben.Hingegen der eigene, explizite
x:Key
des "keyedStyle" ist einfach Text: "keyedStyle", also ein String.Da er keyed ist, kommt dieser Style nur zur Anwendung, wenn ausdrücklich auf ihn verwiesen wird - wie in Zeile
#38
.Im zweiten eingeschachtelten DockPanel findet sich der "middleStyle", auch basierend auf "outerStyle" - BorderBrush-modifiziert -
#25
.Also Label
1
+ 2
sind schwarzgerahmt und rot betextet, weil sie "outerStyle" anwenden.Label
3
+ 4
sind blaugerahmt, weil sie "middleStyle" anwenden.Im innersten DockPanel ist noch ein Style - "innerStyle", der denselben BasedOn-Key verwendet wie die vorherigen beiden Styles. Aber dieser addressiert nun den "middleStyle", welcher "outerStyle" an dieser Stelle ja abschattiert.
Daher "erbt" Label
5
den blauen Rahmen, wenns "innerStyle" auf sich anwendet.Label
6
hingegen hat sich explizit einen keyedStyle zugewiesen, und erhält dadurch den schwarzen Rahmen und die rote Schrift des "outerStyle" - allerdings mit des "keyedStyle"s modifizierter Rahmenbreite.Die SystemColors-Klasse
So - also das mitte Scopes, Explizit-/ Auto-Keys, und die Style-Selbstanwendung bei Auto-Keys muss verstanden sein fürs Folgende.
Ich hab mich heuer mit der statischen Klasse
SystemColors
beschäftigt, darin sind 32 verschiedene Farben definiert, und ihre "Farb-Zwecke" - etwa "Highlight..." - hab ich herausgefunden - wird gern als Hintergrundfarbe von Selektierung genommen - sei es in List- oder Text-boxen or whatever.Wie gesagt: von derlei Farb-Zwecken gibts noch 31 mehr, etwa
"HighlightText": Selection-Schriftfarbe | "Control": Control-Hintergrund | "ControlText": C-Vordergrund | ...
Zu jedem dieser Zwecke fahren inne
SystemColors
-Klasse 3 Objekte rum: eine Color, ein Brush, und ein Brushkey, also zum Highlighten gibts HighlightColor
, HighlightBrush
, HighlightBrushKey
.Warum?
Weil in Wpf auch die Systemfarben einstellbar sind.
Also ein gehighlightetes
Visual
holt mittm HighlightBrushKey
vom Resourcen-Management seinen Brush. Wenn nix anneres festgelegt ist, wird es SystemColors.HighlightBrush
erhalten, aus einem globalen ResourceDictionary als letzte Instanz.Wenn nichts anneres festgelegt ist.
Ich kann ja auch ein eigenes
ResourceDictionary
anlegen, und da kann ich auch einen Brush reinlegen, und dem kann ich denselben Schlüssel geben:Ätsch! - wenn nun ein
Visual
im Scope meines ResourceDictionaries liegt, dann wird es für denselben Key meinen Brush erhalten - nicht mehr den des Systems.Man kann also mit wenigen Zeilen ganze Farb-Themes redefinieren, wenn man das toll findet. Anwendungsweit, aber auch jeder engere Scope: einzelne Fenster, Panels, wie wolle.
Oder man bastelt einen Style speziell für Listboxen:
So - meine Listboxen highlighten jetzt in Khaki, unter Beibehaltung der Textfarbe. Findich viel angenehmer als das Standard-Highlighting mit weissem Text auf DunkelBlau.
Ich hab diesen Style per Scope Super-Hoch aufgehängt - höher noch als Application-Ebene.
Nämlich in meine Wpf-Helpers hab ich ihn in ein ResourceDichtionary gemacht, und alle meine Wpf-Anwendungen inkludieren dieses, zB so:
XML-Quellcode
- <Application x:Class="Application"
- 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"
- mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
- xmlns:vm="clr-namespace:_WpfTemplate.Viewmodel"
- xmlns:vw="clr-namespace:_WpfTemplate.View"
- StartupUri="View/MainWindow.xaml">
- <Application.Resources>
- <ResourceDictionary>
- <ResourceDictionary.MergedDictionaries>
- <ResourceDictionary Source="pack://application:,,,/WpfHelpers;component/Resources/GeneralStyles.xaml"/>
- <!--weitere Resource-Files... -->
- </ResourceDictionary.MergedDictionaries>
- </ResourceDictionary>
- <!--weitere einzelne Resources... -->
- </Application.Resources>
- </Application>
Zeile #13 ist die Include-Anweisung - die Pfad-Angabe ist ein bischen krank - das ist ein
Uri
. Was das pack
, das application
, die 3 ,
, das ;component
da zu bedeuten hat hab ich noch nicht genau begriffen, man kann ja nach "Wpf Uri pack" googeln, da kommen iwelche genauere Erklärungen.Mir reicht erstmal zu wissen, dass
WpfHelpers
meine eingebundene Assymbly ist, und /Resources/GeneralStyles.xaml
ist der Pfad von deren Projekt-Verzeichnis zu meim GeneralStyles-Dictionary-File.Sample-Application
Inne Sample-Application hab ich ausserdem noch was anneres eingebunden, nämlich ein Resource-Dictionary, mit dem man jeden einzelnen FarbZweck auf "Red" umstellen kann. Und dazu habich eine Listbox gebastelt, um die ResourceKeys auszuwählen. Und ein Test-Control, wo man dann sieht, welcher Teil der Controls bei welchem ResourceKey rot wird.
Das Bildle zeigt, wie der HighlightBrushKey des selektierten ListboxItems Hintergrund errötet.
Die Sample-App enthält auch meine Helpers - also nicht erschrecken über die grosse Code-Menge - die eigentliche Haupt-Assembly ist sehr überschaubar.
Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von „ErfinderDesRades“ ()