Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Jetzt Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 23 Konzepte von WPF
Pfeil 23.1 Anwendungsspezifische Ressourcen
Pfeil 23.2 Anwendungsübergreifende Ressourcen
Pfeil 23.2.1 Mehrere Ressourcenwörterbücher
Pfeil 23.2.2 Die Suche nach einer Ressource
Pfeil 23.3 Logische Ressourcen
Pfeil 23.3.1 Statische Ressourcen
Pfeil 23.3.2 Dynamische Ressourcen
Pfeil 23.3.3 Ressourcen mit C#-Code bearbeiten
Pfeil 23.3.4 Abrufen von Systemressourcen
Pfeil 23.4 Styles
Pfeil 23.4.1 Einfache Styles
Pfeil 23.4.2 Typisierte Styles
Pfeil 23.4.3 Erweitern von Styles
Pfeil 23.4.4 EventSetter
Pfeil 23.5 Trigger
Pfeil 23.5.1 Eigenschaftstrigger
Pfeil 23.5.2 Datentrigger
Pfeil 23.5.3 Ereignistrigger
Pfeil 23.6 Templates
Pfeil 23.6.1 Allgemeines zu »ControlTemplates«
Pfeil 23.6.2 Definition innerhalb eines Styles
Pfeil 23.7 Ermitteln des visuellen Elementbaums
Pfeil 23.7.1 Das Tool »Expression Blend«
Pfeil 23.7.2 Standard-Template mit Code abfragen

Rheinwerk Computing - Zum Seitenanfang

23.3 Logische RessourcenZur nächsten Überschrift

Im letzten Abschnitt haben Sie gelernt, wo in einer WPF-Anwendung überall Ressourcen definiert werden können. Nun ist es Zeit, sich mit dem Thema zu beschäftigen, wie eine Ressource definiert wird. Wie Sie im weiteren Verlauf dieses und der folgenden Kapitel noch sehen werden, können Ressourcen sehr vielfältig geprägt sein. Das geht weit darüber hinaus, nur simple Hintergrundfarben einer Anwendung zu verallgemeinern. Tatsächlich ist der Einsatzbereich so weit gesteckt, dass in den Resources-Abschnitten ein Großteil des XAML-Codes zu finden ist.

Zunächst einmal wollen wir uns den als »logische Ressourcen« bezeichneten Ressourcen widmen. Logische Ressourcen sind Objekte, die als Ressourcen definiert sind und innerhalb der Anwendung referenziert werden können.

Logische Ressourcen lassen sich mit Cascading Style Sheets (CSS) vergleichen, die ebenfalls zentral außerhalb ihres Einsatzgebietes definiert werden. Da Sie beliebig viele Ressourcen festlegen können, muss jede Ressource über einen eindeutigen Schlüssel identifizierbar sein. Dieser wird mit dem Key-Attribut beschrieben, das einem Namespace zugeordnet ist, der per Vorgabe durch x: beschrieben wird.

<Window ...>
<Window.Resources>
<LinearGradientBrush x:Key="color">
<GradientStop Color="Black" Offset="0.0" />
<GradientStop Color="White" Offset="1.0" />
</LinearGradientBrush>
</Window.Resources>
[...]
</Window>

Listing 23.5 Definition einer logischen Ressource

Elemente, die Ressourcen referenzieren, verwenden zwei Markup-Erweiterungen:

  • StaticResource
  • DynamicResource

Beispielsweise könnte man eine Schaltfläche mit der in Listing definierten Ressource wie folgt verbinden:

<Button Background="{StaticResource color}">Button 1</Button>

Rheinwerk Computing - Zum Seitenanfang

23.3.1 Statische RessourcenZur nächsten ÜberschriftZur vorigen Überschrift

Der Name StaticResource suggeriert im ersten Moment, dass hiermit eine Ressource statisch eingebunden wird. Das ist auch richtig, aber es stellt sich die Frage, was genau unter statisch zu verstehen ist. Zur Beantwortung hilft das folgende Beispielprogramm. In diesem ist eine Ressource im Abschnitt Window.Resources definiert, die der Einfachheit halber nur ein SolidColorBrush-Objekt beschreibt. Die Ressource wird von einem Button mit StaticResource referenziert. Zwei weitere Schaltflächen dienen dazu, die Ressource auf unterschiedliche Art und Weise zu ändern.

// Beispiel: ..\Kapitel 23\StaticResourceSample
<Window ...>
<Window.Resources>
<SolidColorBrush x:Key="btnBackground" Color="Yellow" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Name="button1" Margin="10" VerticalAlignment="Top" Height="40"
Background="{StaticResource btnBackground}">Button 1</Button>
<StackPanel Grid.Column="1">
<Button Name="btnChangeColor1" Margin="5"
Click="btnChangeColor1_Click">Ressource ändern</Button>
<Button Name="btnChangeColor2" Margin="5,0,5,5"
Click="btnChangeColor2_Click">Ressource erstellen</Button>
</StackPanel>
</Grid>
</Window>

Listing 23.6 XAML-Code des Beispielprogramms »StaticResourceSample«

Zu diesem XAML-Code gehören zwei Ereignishandler, die in der Code-Behind-Datei codiert sind.

private void btnChangeColor1_Click(object sender, RoutedEventArgs e) {
SolidColorBrush brush = (SolidColorBrush)FindResource("btnBackground");
brush.Color = Colors.Red;
}
private void btnChangeColor2_Click(object sender, RoutedEventArgs e) {
SolidColorBrush brush = new
SolidColorBrush(Colors.Green);
this.Resources["btnBackground"] = brush;
}

Listing 23.7 Code der beiden Ereignishandler

Im Ereignishandler der Schaltfläche btnChangeColor1 wird mit FindResource die Referenz auf die Ressource per Schlüssel gesucht und anschließend die Farbe geändert. Im zweiten Ereignishandler wird ein neues Objekt vom Typ SolidColorBrush erzeugt und danach an die existente Ressource btnBackground übergeben.

Der Zugriff auf Ressourcen mit Programmcode (hier mit FindResource) war bisher noch nicht das Thema. Dennoch sollte der C#-Code verständlich sein.

Sie werden feststellen, dass die ressourcengebundene Schaltfläche die Hintergrundfarbe ändert, wenn Sie auf die obere Schaltfläche klicken. Klicken Sie auf die untere, passiert nichts – auch keine Ausnahme. Das ist mit der Verhaltensweise von StaticResource zu erklären. Die Eigenschaft, hier Background der bindenden Komponente, wird an ein Objekt der Ressource SolidColorBrush gebunden. Die Änderung einer Eigenschaft der Ressource (hier Color) wird von der bindenden Komponente erkannt und umgesetzt. Das Klicken der unteren Schaltfläche hingegen hat keine Auswirkungen auf die bindende Komponente, weil im Programmcode ein neues Objekt erzeugt wird.

Zusammenfassend muss man also feststellen, dass StaticResource immer dasselbe Ressourcenobjekt referenziert, aber durchaus in der Lage ist, dessen Eigenschaftsänderungen umzusetzen.

Ein Sonderfall: Elemente als Ressourcen

Als Ressource kann prinzipiell jedes beliebige Objekt verwendet werden. Eine Ressource kann per Vorgabe auch nur einmal instanziiert werden. Jeder Zugriff, ob im XAML- oder im C#-Programmcode, ist ein Zugriff auf dieselbe Instanz.

Diese Charakteristik der Ressourcen führt uns in eine Situation, die wir an dieser Stelle betrachten müssen. Bisher haben wir nur mit einem einfachen Brush-Objekt die Ressource beschrieben. Es ist aber auch denkbar, ein Steuerelement in einer Ressource zu beschreiben. Im nächsten Beispiel wird dazu ein Image genommen, das ein Bildchen beschreibt.

// Beispiel: ..\Kapitel 23\StaticResourceWithControl
<Window ...>
<Window.Resources>
<Image x:Key="image" Source="smiley.jpg" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="{StaticResource image}" />
<Button Grid.Column="1" Content="{StaticResource image}"/>
</Grid>
</Window>

Listing 23.8 XAML-Code des Beispielprogramms »StaticResourceWithControl«

Nach dem Start der Anwendung werden Sie feststellen, dass die Ressource nur einmal genutzt wird (siehe Abbildung 23.2).

Abbildung

Abbildung 23.2 Ausgabe des Beispielprogramms »StaticResourceWithControl«

Der Grund ist, dass ein Image Teil des Elementbaums ist und nur einmal verwendet werden kann. Die Brush-Objekte, die wir vorher als Ressourcen definiert hatten, sind nicht Teil des Elementbaums und konnten daher von mehreren Elementen verwendet werden.

Eine Lösung des Problems wird natürlich von der WPF angeboten. Per Vorgabe werden die Ressourcenobjekte nur einmal instanziiert. Jedes Element, das dieselbe Ressource referenziert, erhält dieselbe Referenz. Wird die Ressource jedoch mit dem Attribut x:Shared=false erweitert, wird die Ressource bei jedem Zugriff instanziiert. Die Standardeinstellung des Attributs ist demzufolge true. Ändern Sie also die Ressource wie im folgenden Listing ab:

<Image x:Key="image" Source="smiley.jpg" x:Shared="false" />

Listing 23.9 Ressource mehrfach instanziieren

Danach wird die Anwendung die Ressource so benutzen, wie Sie es sich vorgestellt haben (siehe Abbildung 23.3).

Abbildung

Abbildung 23.3 Ausgabe des Beispielprogramms »StaticResourceWithControl« nach der Änderung


Rheinwerk Computing - Zum Seitenanfang

23.3.2 Dynamische RessourcenZur nächsten ÜberschriftZur vorigen Überschrift

Ganz anders als statische Ressourcen verhalten sich Ressourcen, die mit DynamicResource eingebunden werden. Eine Änderung der Referenz der Ressource wird dazu führen, dass die bindende Komponente die neue Ressource zur Kenntnis nimmt und darauf entsprechend reagiert. Sie können das sehr leicht ausprobieren, wenn Sie im Beispielprogramm StaticResourceSample die Bindung mit StaticResource gegen DynamicResource austauschen, also:

[...]
<Button Name="button1" Margin="10" VerticalAlignment="Top" Height="40"
Background="{DynamicResource btnBackground}">Button 1</Button>
[...]

Listing 23.10 Änderung im Beispielprogramm »StaticResourceSample«

Jetzt werden beide Schaltflächen genau die Verhaltensweise zeigen, die von ihnen erwartet wird. Weiterhin wird die Änderung der Eigenschaft Color der Schaltfläche btnChangeColor1 dazu führen, dass die bindende Schaltfläche sich aktualisiert, aber auch das Anklicken der unteren Schaltfläche btnChangeColor2 führt zu dem erwarteten Erfolg.

Es mag im ersten Moment verlockend sein, immer mit DynamicResource an Ressourcen zu binden. Sie sollten sich das aber genau überlegen, da jeder dynamische Vorgang immer zu Lasten der Performance geht. Das gilt selbstverständlich auch für DynamicResource. Wenn Sie davon ausgehen können, dass sich die Ressource nicht ändert, sollten Sie daher immer mit StaticResource binden.


Rheinwerk Computing - Zum Seitenanfang

23.3.3 Ressourcen mit C#-Code bearbeitenZur nächsten ÜberschriftZur vorigen Überschrift

Alles, was in XAML möglich ist, kann auch mit Programmcode erreicht werden. Dazu zählt auch die Suche nach einer Ressource und deren Anbindung an eine Eigenschaft. Im Beispielprogramm StaticResourceSample wurde bereits eine Ressource mit Code geändert. Es ist nun an der Zeit, hierzu die entsprechenden Hintergründe zu beleuchten.

Zuweisung einer statischen Ressource

Am einfachsten gestaltet sich der Zugriff auf eine statische Ressource, wenn sich die Ressource im aktuellen Fenster befindet und sie namentlich bekannt ist. Mit der Eigenschaft Resources rufen Sie die Ressource ab und geben dabei den Namen der gesuchten Ressource an. Angenommen, die Ressource background sei unter Window.Resources definiert, würde die Anweisung wie folgt lauten:

button1.Background = (Brush)Resources["background"];

Listing 23.11 Ressource innerhalb des Fensters mit »Resources« lokalisieren

Die gefundene Ressource muss noch in den entsprechenden Typ konvertiert werden, weil jeder Ressourceneintrag vom Typ Object ist. Da die Hintergrundfarbe einer Schaltfläche vom Typ Brush ist, erfolgt die Konvertierung in der vorangehenden Anweisung in genau diesen Typ.

Befindet sich die Ressource nicht im aktuellen Fenster, eignet sich die gezeigte Anweisung nicht. Stattdessen muss die Ressource in der gesamten Hierarchie gesucht werden. Hierzu eignet sich die Methode FindResource, die jedes Steuerelement hat. Sie rufen die Methode auf das Objekt auf, dem die Ressource zugewiesen werden soll, und übergeben als Argument den Bezeichner der Ressource. Die gefundene Ressource muss natürlich ebenfalls in den Datentyp der entsprechenden Eigenschaft konvertiert werden.

button1.Background = (Brush)button1.FindResource("background");

Listing 23.12 Ressource mit »FindResource« lokalisieren

Wird die angegebene Ressource nicht gefunden, ist eine Exception die Folge. Daher ist es in vielen Fällen vorteilhaft, alternativ die Methode TryFindResource zu benutzen. Im Gegensatz zu FindResource liefert TryFindResource eine null-Referenz, falls die Ressource nicht gefunden wird.

Zuweisung einer dynamischen Ressource

Mit den Methoden FindResource und TryFindResource wird die Markup-Erweiterung StaticResource mittels Code beschrieben. Eine Ressource dynamisch zu binden, ist mit diesen Methoden nicht möglich. Zur Anbindung an eine dynamische Ressource dient die Methode SetResourceReference. Die Methode hat zwei Parameter. Dem ersten wird die Abhängigkeitseigenschaft übergeben, die an die Ressource dynamisch gebunden werden soll, dem zweiten Parameter der Ressourcenbezeichner.

button1.SetResourceReference(Button.BackgroundProperty, "background");

Listing 23.13 Dynamische Ressource mit »SetResourceReference« binden

Beachten Sie hierbei, dass die Angabe einer Abhängigkeitseigenschaft (Dependency Property) erfordert, diese direkt zu benennen, in unserem Fall demnach Button.BackgroundProperty.


Rheinwerk Computing - Zum Seitenanfang

23.3.4 Abrufen von SystemressourcenZur nächsten ÜberschriftZur vorigen Überschrift

Bisher haben wir nur benutzerdefinierte Ressourcen verwendet. Sie können aber auch auf Ressourcen zugreifen, die vom System bereitgestellt werden. WPF enthält im Namespace System.Windows drei Klassen, mit denen sich bestimmte Eigenschaften des Systems auswerten lassen:

  • SystemParameters
  • SystemColors
  • SystemFonts

SystemFonts beschreibt Eigenschaften, die die Systemressourcen für Schriftarten verfügbar machen, SystemColors beschreibt die vom System verwendeten Farben, und SystemParameters enthält Eigenschaften, die Sie zum Abfragen von Systemeinstellungen verwenden können. Die drei Klassen enthalten in ihren Eigenschaften immer die aktuellen Werte des Betriebssystems, die von den Einstellungen in der Systemsteuerung abhängen.

Wenn Sie sich die Dokumentation dieser Klassen ansehen, werden Sie feststellen, dass für jede Systemeigenschaft zwei Eigenschaften definiert sind, zum Beispiel

  • CaptionHeight
  • CaptionHeightKey

in der Klasse SystemParameters. Doch wozu braucht man zwei ähnliche Eigenschaften?

CaptionHeight ist vom Typ double und gibt die Höhe der Titelleiste in Pixeln an. CaptionHeightKey hingegen ist vom Typ ResourceKey. Darüber wird der Name der Systemressource gekennzeichnet, die den Wert der Eigenschaft zurückliefert.

Möchten Sie auf eine Ressource statisch zugreifen, reicht die Angabe der Eigenschaft ohne das Suffix Key vollkommen aus. In diesem Fall reagiert die Anwendung nicht auf Änderungen an den Systemeinstellungen. Sehen wir uns eine statische Ressourcenabfrage an. Beachten Sie, dass für den Zugriff auf die Systemressourcen die Markup-Erweiterung x:Static vorgeschrieben ist.

<Label Content="{StaticResource {x:Static SystemParameters.CaptionHeightKey}}" />

Die Angabe der Markup-Erweiterung StaticResource bewirkt, dass eine Suche nach der Ressource entlang der Hierarchie angestoßen wird. Das geht zu Lasten der Performance.

Mit der XAML-Markup-Erweiterung x:Static greift man auf die statischen Eigenschaften, Felder oder Konstanten einer Klasse oder Aufzählung zu.

Besser ist es, direkt auf den Wert der Eigenschaft mit

<Label Content="{x:Static SystemParameters.CaptionHeight}"  />

zuzugreifen. Im C#-Code können Sie den Wert der Eigenschaft mit

double height = SystemParameters.CaptionHeight;

ermitteln.

Bei einer Änderung des Werts in der Systemsteuerung nimmt die Anwendung zur Laufzeit keine Notiz von der Änderung. Soll sich die Anwendung der Änderung anpassen, müssen Sie die Ressource mit DynamicResource einbinden.

<Label Content="{DynamicResource {x:Static SystemParameters.CaptionHeightKey}}"/>

Systemressourcen anpassen

Wie weiter oben schon erläutert, läuft die Suche nach einer bestimmten Ressource nach einem vorgegebenen Schema ab. Sie beginnt im Logical Tree bei dem Element, auf dem die Markup-Erweiterung StaticResource oder DynamicResource verwendet oder die Methode FindResource aufgerufen wird. Wird die Ressource nicht gefunden, wird im Application-Objekt danach gesucht. Die letzte Ebene der Suche bilden die Systemressourcen, in denen sich die Einstellungen des Betriebssystems befinden.

Dieser Suchprozess gestattet, eine »höher liegende« Ressource durch eine tiefer liegende zu überschreiben, denn sobald die Suche erfolgreich war, wird sie beendet. Folglich lassen sich auch die vorgegebenen Systemressourcen sehr einfach durch anwendungsspezifische ersetzen.

Damit ist es beispielsweise sehr einfach, die Hintergrundfarbe aller Fenster einer Anwendung festzulegen. Verantwortlich dafür ist die Ressource WindowBrushKey in der Klasse SystemColors. Wünschen Sie einen roten Hintergrund bei allen Fenstern der Anwendung, ergänzen Sie den Resource-Abschnitt der Datei App.xaml einfach wie folgt:

<Application.Resources>
<SolidColorBrush Color="Red" x:Key="{x:Static SystemColors.WindowBrushKey}" />
</Application.Resources>

Einen Farbverlauf festzuschreiben ist mit der Ressource WindowBrushKey nicht möglich, da der durch diese Ressource beschriebene Wert vom Typ SolidColorBrush ist.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern