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 18 Einführung in die WPF und XAML
Pfeil 18.1 Die Merkmale einer WPF-Anwendung
Pfeil 18.1.1 Anwendungstypen
Pfeil 18.1.2 Eine WPF-Anwendung und deren Dateien
Pfeil 18.1.3 Ein erstes WPF-Beispiel
Pfeil 18.1.4 Wichtige WPF-Features
Pfeil 18.1.5 Der logische und der visuelle Elementbaum
Pfeil 18.2 XAML (Extended Application Markup Language)
Pfeil 18.2.1 Die Struktur einer XAML-Datei
Pfeil 18.2.2 Eigenschaften eines XAML-Elements in Attributschreibweise festlegen
Pfeil 18.2.3 Eigenschaften im Eigenschaftsfenster festlegen
Pfeil 18.2.4 Die Eigenschaft-Element-Syntax
Pfeil 18.2.5 Inhaltseigenschaften
Pfeil 18.2.6 Typkonvertierung
Pfeil 18.2.7 Markup-Erweiterungen (Markup Extensions)
Pfeil 18.2.8 XML-Namespaces
Pfeil 18.2.9 XAML-Spracherweiterungen

18 Einführung in die WPF und XAMLZur nächsten Überschrift

Mit der Einführung von .NET 1.0 wurde eine neue Technologie zur Entwicklung von Windows-Anwendungen eingeführt: die WinForm-API. Im Grunde genommen war die WinForm-API keine Neuentwicklung, da sie die Windows-API nutzte. Trotz der Erweiterung der Windows-API wurde an der grundlegenden Architektur nichts verändert.

Unter dem Codenamen Avalon startete Microsoft Mitte des letzten Jahrzehnts die Entwicklung einer neuen Bibliothek für grafische Benutzeroberflächen, die im Jahr 2006 unter dem Bezeichner Windows Presentation Foundation (WPF) als Teil von .NET 3.0 veröffentlicht worden ist. Bereits in Visual Studio 2008 wurde die WPF neben der traditionellen Technologie für die WinForm-API fest in die Entwicklungsumgebung integriert. Nach einigen Startschwierigkeiten, die nicht nur auf Mängel zurückzuführen sind, fand die WPF eine breite Akzeptanz in der Entwicklergemeinde und gehört nunmehr zur bevorzugten Technologie zur Entwicklung von Windows-Anwendungen.

In den kommenden Kapiteln werden wir uns mit WPF beschäftigen. Dabei können wir nicht alle Aspekte und Konzepte berücksichtigen. Aber ich möchte Ihnen einen Einstieg in die Technologie geben und Ihnen zeigen, wie Windows-Anwendungen mit der WPF entwickelt werden. Sie werden feststellen, dass die Lernkurve nicht so steil ist wie bei der nun auf das Abstellgleis geschobenen WinForm-API.

Nach Aussagen von Microsoft wird die WinForm-API nicht mehr weiterentwickelt. Dennoch ist sie auch weiterhin elementarer Bestandteil in Visual Studio 2012 und wird es meiner Ansicht nach auch noch länger bleiben. Im Grunde genommen brauchen Sie nicht zu fürchten, ein neues Projekt mit der WinForm-API zu starten, aber andererseits sind Sie dann nicht mehr up to date und können die vielen interessanten und auch positiv zu bewertenden Programmiertechniken nicht nutzen. Sollten Sie in Zukunft, aus welchen Gründen auch immer, planen, Ihre WinForm-Anwendung auf WPF umzustellen, fangen Sie von vorne an. Die Frage, ob WinForms oder WPF, sollte sich somit eigentlich gar nicht stellen.


Rheinwerk Computing - Zum Seitenanfang

18.1 Die Merkmale einer WPF-AnwendungZur nächsten ÜberschriftZur vorigen Überschrift

Am Anfang stellt sich zuerst die Frage, welche typischen Charakteristika eine WPF-Anwendung auszeichnen und wo die Vorteile im Vergleich zu den WinForms zu suchen sind. Die folgende Liste soll diese Fragen beantworten.

  • Die Benutzeroberfläche wird mit einer an XML angelehnten Sprache beschrieben: mit XAML (eXtensible Application Markup Language, gesprochen Xemmel). Dadurch wird es möglich, die Beschreibung der Benutzeroberfläche vom Code strikt zu trennen – ähnlich wie es mit ASP.NET bereits seit Jahren mit dem sogenannten Code-Behind-Modell der Fall ist. XAML ist ausgesprochen mächtig und offenbart erstaunliche Fähigkeiten. Zusammen mit den in WPF eingeführten Konzepten werden Sie vergleichsweise wenig Programmcode schreiben, sondern sich mehr auf XAML konzentrieren. Die Folge wird sein, dass der XAML-Code sehr umfangreich werden kann, während der reine C#-Code sich nur noch auf wenige Operationen beschränkt.
  • WPF-Anwendungen bieten eine umfangreiche Unterstützung von 2D- und 3D-Grafiken. Dabei wird die schnelle Grafikausgabe durch DirectX genutzt. Das wiederum bedeutet, dass die Grafikkarte zur Berechnung der grafischen Elemente herangezogen wird und nicht die CPU. Das führt zu einer deutlich verbesserten Performance.
  • WPF-Anwendungen bieten vielfältige Datenbindungsmöglichkeiten für die Komponenten. Das ist mit Sicherheit eine der stärksten Seiten der WPF. Deshalb werden wir uns mit dieser Thematik noch intensiv auseinandersetzen. Andererseits muss man hinsichtlich der Datenbindungsmöglichkeiten auch einen der großen Nachteile der WPF anführen: Die Unterstützung von ADO.NET lässt doch zu wünschen übrig, während das Entity Framework sehr gut unterstützt wird.
  • Die WPF-Ausgabe ist vektorbasiert. Das bedeutet, dass auch beim Skalieren keine hässlichen Pixel zu sehen sind, sondern immer ein fließender Verlauf der grafischen Darstellung.
  • WPF-Anwendungen bieten vielfältige grafische Unterstützung, z. B. für die Darstellung der Steuerelemente, grafische Animationen, Unterstützung von Videos, Bildern und Audio-Dateien.
  • Grundsätzlich besteht die Möglichkeit, eine Benutzeroberfläche bereitzustellen, die entweder in einem herkömmlichen Fenster oder im Browser angezeigt wird.
  • Im Vergleich zur WinForm-API gibt es neue Layoutoptionen durch Verschachtelung der Elemente. Damit bietet die WPF im Vergleich zur WinForm-API deutlich bessere Gestaltungsmöglichkeiten.
  • Nicht unerwähnt bleiben sollte auch, dass die WPF ein altes Problem der WinForms gelöst hat. Früher war es kaum möglich, das Fenster automatisch an die Monitorauflösung (DPI) anzupassen. Das konnte dazu führen, dass Randbereiche von Dialogen möglicherweise nicht mehr angezeigt wurden und im Extremfall einige Bedienelemente der Oberfläche unerreichbar waren.

Die grafischen Fähigkeiten von WPF stellen alles Vergangene deutlich in den Schatten. Wollen Sie runde Buttons? Kein Problem. Wollen Sie runde Fenster? Ebenfalls kein Problem. Neben den Vorteilen der grafischen Gestaltung können auch andere Gesichtspunkte wie die der umfangreichen Datenbindungsmöglichkeiten die Entscheidung für die WPF und somit gegen die WinForm-API beeinflussen. Darüber hinaus muss bei der Entscheidungsfindung auch noch berücksichtigt werden, dass Microsoft die WinForm-API nicht mehr weiterverfolgt und voll auf WPF setzt, die inzwischen bekanntermaßen auch schon in Silverlight eingeflossen ist.

Die strikte Trennung von Oberflächenbeschreibung und Code gestattet es, dass die Oberfläche von einem Grafiker gestaltet wird, während der Entwickler den Code dazu schreibt. Die Oberflächenbeschreibung erfolgt in XAML, während die Programmlogik in C#, VB.NET oder einer anderen .NET-Sprache codiert werden kann. Übrigens gibt es von Microsoft mit Expression Blend ein Tool, das vornehmlich für Designer gedacht ist.


Rheinwerk Computing - Zum Seitenanfang

18.1.1 AnwendungstypenZur nächsten ÜberschriftZur vorigen Überschrift

Visual Studio 2012 bietet Ihnen im Zusammenhang mit der WPF vier verschiedene Projektvorlagen an:

  • WPF-Anwendung
  • WPF-Browseranwendung
  • WPF-Benutzersteuerelementbibliothek
  • Benutzerdefinierte WPF-Steuerelemente

Abbildung

Abbildung 18.1 WPF-Projektvorlagen

WPF-Anwendung

Dieser Anwendungstyp entspricht im Wesentlichen einer herkömmlichen Windows-Anwendung. Die charakteristischen Eigenschaften gleichen denen einer WinForm-Anwendung. WPF-Anwendungen werden in einem eigenen Fenster ausgeführt und können mit dem MS Installer (MSI) oder ClickOnce installiert werden. Mit beiden Installationsvarianten werden wir uns im letzten Kapitel dieses Buches noch beschäftigen.

WPF-Browseranwendung

Im Gegensatz zu WPF-Anwendungen stellen WPF-Browseranwendungen keine eigenen Fenster bereit – die Ausgabe erfolgt im Browser. Außerdem werden WPF-Browseranwendungen nicht auf der lokalen Maschine installiert, was zur Folge hat, dass es nicht möglich ist, einen Verweis auf die Anwendung im Startmenü zu hinterlegen.

Benutzerdefinierte WPF-Steuerelementbibliothek (User Control)

Visual Studio 2012 stellt zwei Projektvorlagen zum Entwickeln eigener Steuerelemente bereit. Die Variante mit einem User Control ist die einfachere von beiden. Etwas vereinfacht gesagt, wird dabei ein neues Steuerelement aus mehreren bestehenden Steuerelementen gebildet.

WPF-Benutzersteuerelementbibliothek (Custom Control)

Der Aufwand, ein Custom Control zu entwickeln, ist deutlich größer, hat aber im Vergleich zu den User Controls auch Vorteile. Beispielsweise kann ein Custom Control durch Templates angepasst werden.


Rheinwerk Computing - Zum Seitenanfang

18.1.2 Eine WPF-Anwendung und deren DateienZur nächsten ÜberschriftZur vorigen Überschrift

Wir wollen nun ein erstes Projekt vom Typ WPF-Anwendung starten und uns zuerst die Entwicklungsumgebung ansehen.

Im oberen Bereich des Editors wird das Fensterdesign angezeigt, der dazu gehörige XAML-Code erscheint darunter. Hier gestalten Sie die Oberfläche des Fensters, indem Sie Steuerelemente aus dem Werkzeugkasten (auch als Toolbox tituliert), der standardmäßig am linken Rand angezeigt wird, in den Designer ziehen oder alternativ das gewünschte Steuerelement direkt in den XAML-Code schreiben. Beide Teilbereiche, der Designer und der XAML-Code, synchronisieren sich bei einer Änderung gegenseitig.

Werfen Sie einen Blick in den Projektmappen-Explorer (siehe ). Hier finden Sie unter anderem mit App.xaml, App.xaml.cs, MainWindow.xaml und MainWindow.xaml.cs vier Dateien, die wir uns nun genauer ansehen.

Abbildung

Abbildung 18.2 Die Entwicklungsumgebung einer WPF-Anwendung

Die Datei »MainWindow.xaml«

In dieser Datei steckt der XAML-Code des Fensters, den Sie im unteren Bereich des Code-Editors sehen.

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>

Listing 18.1 Der standardmäßig erzeugte XAML-Code eines Fensters

In der ersten Zeile wird mit x:Class="WpfApplication1.MainWindow der Bezug zum C#-Code hergestellt. Danach sind mit xmlns zwei Namespaces angegeben, denen mit Title die Beschriftung der Titelleiste folgt. Height und Width geben die Ausgangsgröße des Fensters an.

Alle Steuerelemente einer WPF-Anwendung positionieren sich innerhalb eines Layout-Containers. Mit Grid wird sofort ein Vorschlag gemacht, den Sie aber nach eigenem Ermessen durch einen anderen Container ersetzen können. Die Container werden in Kapitel 19 besprochen.

Die Datei »MainWindow.xaml.cs«

MainWindow.xaml ist die Datei, in der die Oberfläche des Fensters beschrieben wird. Bei MainWindow.xaml.cs handelt es sich um die Datei, in der Sie den Programmcode schreiben. Diese Datei wird auch als Code-Behind-Datei bezeichnet. Wie üblich werden Sie hier die Ereignishandler implementieren, Eigenschaften und Felder beschreiben usw. Die Datei weist nicht viel Inhalt auf. Einzig und allein der parameterlose Standardkonstruktor, in dem die Methode InitializeComponent aufgerufen wird, ist dort zu finden.

using System;
[...]
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

Listing 18.2 Der Inhalt der Datei »MainWindow.xaml.cs«

Die Methode InitializeComponent lädt die für das Fenster benötigten Komponenten, die in der Datei MainWindow.xaml definiert sind, indem die statische Methode LoadComponent der Klasse Application aufgerufen wird.

Die Datei »App.xaml«

Auch zu dieser Datei gehört eine Code-Behind-Datei, die mit dem Attribut x:Class angegeben wird. Mit xmlns werden hier zwei Namespaces angegeben, und das Attribut StartupUri gibt an, mit welchem Fenster die Anwendung gestartet werden soll.

<Application x:Class="WpfApplication1.App"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

Listing 18.3 Der XAML-Code in der Datei »App.xaml«

Im Bereich zwischen dem einleitenden Tag <Application.Resources> und dem ausleitenden </Application.Resources> können Sie anwendungsweit bekannte Ressourcen eintragen.

Die Datei »App.xaml.cs«

Hierbei handelt es sich um die Code-Behind-Datei zu App.xaml. Sie definiert die Klasse App, die von Application abgeleitet ist, und weist noch keinen Code auf. Die Klasse App veröffentlicht Eigenschaften und löst Ereignisse aus, auf die Sie hier reagieren können.

using System;
[...]
namespace WpfApplication1
{
public partial class App : Application
{
}
}

Listing 18.4 Der Code der Datei »App.xaml.cs«


Rheinwerk Computing - Zum Seitenanfang

18.1.3 Ein erstes WPF-BeispielZur nächsten ÜberschriftZur vorigen Überschrift

Ein paar allgemeine Dinge rund um WPF-Anwendungen haben Sie nun erfahren. Wahrscheinlich sind Sie auch schon gespannt, wie die Oberfläche einer WPF-Anwendung tatsächlich aussehen kann. Um Ihnen ein Gefühl dafür zu vermitteln, sehen Sie sich bitte die folgende Abbildung 18.3 einer – zugegebenermaßen – sehr einfachen Oberfläche an. Wir werden ein sehr ähnliches Beispiel später in diesem Buch wiederfinden. An dieser Stelle soll es nicht darauf ankommen, irgendwelche Details zu beschreiben, vielmehr kommt es darauf an, einen ersten Eindruck zu bekommen.

Abbildung

Abbildung 18.3 Eine erste, einfache WPF-Oberfläche

Dieser Benutzeroberfläche (auch als GUI, für Graphical User Interface bezeichnet) liegt der folgende XAML-Code zugrunde:

<Window x:Class="SimpleBinding.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="Einfache GUI" Height="230" Width="350">
<Window.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF606079" Offset="0" />
<GradientStop Color="WhiteSmoke" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Window.Resources>
<Style x:Key="style1">
<Setter Property="Control.Margin" Value="10, 0, 20, 0" />
<Setter Property="Control.Foreground" Value="White" />
<Setter Property="Control.VerticalAlignment" Value="Center" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Background="Black" Grid.ColumnSpan="2">
<Label Foreground="White" FontSize="16"
HorizontalAlignment="Center">Personendaten</Label>
</StackPanel>
<Label Style="{StaticResource style1}" Grid.Row="1" >Name:</Label>
<TextBox Grid.Column="1" Grid.Row="1"
Text="{Binding Path=Name}" Margin="10" />
<Label Style="{StaticResource style1}" Grid.Row="2">Alter:</Label>
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Path=Alter}"
Margin="10" />
<Label Style="{StaticResource style1}" Grid.Row="3">Adresse:</Label>
<TextBox Grid.Column="1" Grid.Row="3"
Text="{Binding Path=Adresse}" Margin="10" />
<Button Grid.Row="4" Grid.Column="1" Width="120"
HorizontalAlignment="Right"
Margin="0, 0, 10, 0">Bestätigen</Button>
</Grid>
</Window>

Listing 18.5 Der XAML-Code des Fensters aus Abbildung 18.3

Lassen Sie uns einen kleinen Blick auf den XAML-Code werfen, ohne dabei die Details genau zu beschreiben. Diese werden Sie im Laufe der folgenden Kapitel erfahren. Zudem sei auch angemerkt, dass dieses einfache Beispiel nicht alle Möglichkeiten der WPF beinhalten kann oder soll.

Eingerahmt wird der gesamte XAML-Code durch das Element Window. In diesem ist alles im Zusammenhang mit der Darstellung des Fensters (und auch noch mehr) enthalten.

Im Window-Element finden Sie den durch <Grid>...</Grid> eingerahmten Bereich, der die Oberfläche mit Ihren Steuerelementen enthält. Ein Window kann nur exakt ein solches als Container-Control bezeichnetes Steuerelement enthalten. Container-Controls teilen den sogenannten Clientbereich des Fensters auf, arrangieren damit gewissermaßen die enthaltenen Steuerelemente. StackPanel, Canvas oder auch DockPanel sind ebenfalls typische Vertreter solcher Container-Controls. Einige Label-Controls, TextBox-Controls und ein Button bilden die Gesamtheit der Steuerelemente in diesem Fenster.

In der Sektion <Window.BackGround>...</Window.BackGround wird der Hintergrund des Fensters festgelegt. Hier sehen Sie, dass auch im Grunde genommen einfache Eigenschaften (hier BackGround) durch Verschachtelung zu interessanten Effekten führen können. Diese Elementverschachtelung beschränkt sich jedoch nicht nur auf grafische Komponenten. Auch Steuerelemente lassen sich in gleicher Weise verschachteln. Mit dieser Technik können Sie letztendlich Steuerelemente nach eigenen Vorstellungen aufbauen und ihnen eine eigene Charakteristik geben. Das ist übrigens mit ein Grund, weshalb die WPF im Vergleich zu der herkömmlichen WinForm-API mit verhältnismäßig wenig Steuerelementen auskommt.

Ein weiterer wichtiger Abschnitt innerhalb des Fensters wird durch <Window.Resources>...</Window.Resources> beschrieben. Bei vielen WPF-Fenstern ist das der Bereich, der den meisten XAML-Code enthält. In unserem kleinen Beispiel wird hier nur ein sogenannter Style beschrieben, der von einigen Label-Steuerelementen benutzt wird, um die im Style aufgeführten Eigenschaftseinstellungen gemeinsam zu nutzen. Das Prinzip erinnert doch sehr an die Cascading Style Sheets (CCS) in HTML-Seiten.

Der XAML-Code dient aber nicht nur dazu, eine neue Art der Oberflächenbeschreibung zu bieten. Die Fähigkeiten gehen noch deutlich weiter. Verhaltensweisen und Techniken, die früher nur durch Programmcode ausgedrückt werden konnten, lassen sich mit XAML umsetzen. Das führt zwangsläufig dazu, dass der Code der Operationen, die im Hintergrund ablaufen, deutlich reduziert werden kann. Andererseits können Sie selbstverständlich alles das, was mit XAML ausgedrückt wird, auch mit C#-Code erreichen.

Wie Sie bereits an diesem einfachen Beispiel erkennen können, ist der XAML-Code relativ umfangreich. Ich werde daher bei vielen der folgenden Beispielprogramme nicht alle Einzelheiten des XAML-Codes im Detail angeben, sondern mich zumeist auf die wesentlichen Merkmale beschränken.


Rheinwerk Computing - Zum Seitenanfang

18.1.4 Wichtige WPF-FeaturesZur nächsten ÜberschriftZur vorigen Überschrift

Dass die WPF-Oberflächen anders gestaltet werden als beispielsweise die GUI einer WinForm-Anwendung, konnten Sie im letzten Beispiel sehen. Die WPF wartet noch mit zahlreichen Features auf, die bisher noch keine Erwähnung fanden. Alle möchte und kann ich Ihnen an dieser Stelle noch nicht aufzählen, aber auf zwei muss ich an dieser Stelle bereits eingehen, da sie erst in einem späteren Kapitel ausführlich erörtert werden, die Begriffe aber bereits im Vorfeld immer wieder erwähnt werden. Dabei handelt es sich um die Dependency Properties und die Routed Events.

Dependency Properties

Das Konzept der Eigenschaften haben wir in Kapitel 3 dieses Buches behandelt: Eine private deklarierte Variable innerhalb einer Klasse wird durch eine Property, die einen get- und einen set-Zweig enthält, veröffentlicht. Nennen wir solche Eigenschaften im weiteren Verlauf einfach CLR-Eigenschaften. Jedes Objekt besitzt einen Pool von Eigenschaften, bei gleichen Typen ist auch deren Anzahl gleich.

Die WPF führt einen ganz anderen Eigenschaftstypus ein: die Dependency Properties, die im Deutschen auch als Abhängigkeitseigenschaften bezeichnet werden. Das Konzept ist ein ganz anderes. Alle Eigenschaften eines bestimmten Typs liegen in einem gemeinsam nutzbaren Container – zumindest solange die Dependency Property nicht von einem definierten Standardwert abweicht. Wird eine Abhängigkeitseigenschaft eines Objekts aber individuell für das Objekt festgelegt, wird die Eigenschaft zu einer objektspezifischen.

Dependency Properties sind mit zahlreichen eigenen Verhaltensmerkmalen ausgestattet. Dazu zählt beispielsweise auch, dass die Bindung an ein anderes Element voraussetzt, dass die bindende Eigenschaft eine Dependency Property ist. Sie finden ein solches Beispiel übrigens in Listing 18.5. Hier ist es unter anderem der Ausdruck Text="{Binding Path=Name}" eines der Label-Steuerelemente. Die Eigenschaft Text des Labels wird an ein Objekt gebunden und hier wiederum an dessen Eigenschaft Name (das Objekt ist im XAML-Code des Listings nicht beschrieben). Da die Text-Eigenschaft gebunden wird, muss sie als Abhängigkeitseigenschaft implementiert sein.

Das sollte in diesem Moment als Information genügen. In Kapitel 26 werde ich Ihnen zeigen, wie Dependency Properties codiert werden.

Im Zusammenhang mit den Dependency Properties muss noch eine verwandte Eigenschaftsgruppe erwähnt werden: die Attached Properties (im Deutschen auch als angehängte Eigenschaften bezeichnet). Als angehängte Eigenschaften werden solche bezeichnet, die ein Steuerelement zwar hat, die aber nicht im Steuerelement selbst definiert werden, sondern in einem hierarchisch übergeordneten. Auch dazu findet sich in Listing 18.5 ein Beispiel. Es handelt sich um alle Angaben von Grid.Column und Grid.Row. Mit diesen Eigenschaften wird die Position des betreffenden Steuerelements im Container-Control beschrieben, das durch ein Grid-Element beschrieben wird. Das Grid stattet mit den beiden genannten Eigenschaften alle ihm untergeordneten Controls aus. Würden die betroffenen Steuerelemente in einem anderen Container liegen, gäbe es diese beiden Eigenschaften nicht.

Auch angehängte Eigenschaften werden in Kapitel 26 erläutert.

Routed Events

In Listing 18.5 ist sehr schön zu erkennen, dass XAML es ermöglicht, verschiedene Elemente ineinander zu verschachteln. Dieses Konzept kann in Konsequenz dazu führen, dass innerhalb eines Button-Elements ein Label positioniert ist, innerhalb dessen wiederum ein Image-Element zu finden ist. Berücksichtigt man dazu noch, dass der Button innerhalb einer Grid-Zelle positioniert ist, die ihrerseits dem Window-Element untergeordnet ist, ergibt sich die folgende Elementhierarchie:

<Window>
<Grid>
<Button ...>
<Label ...>
<Image ... />
</Label>
</Button>
</Grid>
</Window>

Listing 18.6 Verschachtelung verschiedener WPF-Elemente

Nehmen wir nun an, der Anwender würde auf das Image-Element klicken. Betrachten wir die Situation ganz nüchtern, müssen wir uns die Frage stellen, ob mit der Aktion tatsächlich das Image angeklickt werden sollte oder der entsprechende Button. Mit den herkömmlichen Techniken der Events ist diese Frage einfach zu beantworten, denn ohne besondere Maßnahmen kann nur das Image das Ereignis behandeln.

Genau an dieser Stelle kommen die Routed Events ins Spiel. Routed Events leiten die Ereignisse an übergeordnete Elemente weiter. Dabei kommt es zu zwei Ereignisketten: Zuerst werden die getunnelten Events (engl.: Tunneled Events) ausgelöst, die beim Window starten und über das Grid, den Button und das Label am Ende beim Image landen. Anschließend werden die Ereignisse zurückgebubbelt (engl.: Bubbled Events). Diesmal geht die Ereigniskette beim Image los und setzt sich über das Label, den Button, das Grid bis zurück zum Ausgangspunkt Window fort.

Auch den Routed Events wird in diesem Buch ein eigenes Kapitel gewidmet, in dem Sie mehr dazu erfahren (Kapitel 27).

Nicht alle Ereignisse in der WPF werden als Routed Events definiert. Die Gruppe der Ereignisse, die nur von dem Element, bei dem das Ereignis aufgetreten ist, verarbeitet werden, werden im Kontext der WPF als direkte Events bezeichnet. Diese Ereignisse unterscheiden sich nicht von den sonst üblichen im .NET Framework.

Streng genommen gehören auch direkte Events zu den Routed Events, obwohl sie nicht geroutet werden. Dieser scheinbare Widerspruch erklärt sich aber im Laufe von Kapitel 27.


Rheinwerk Computing - Zum Seitenanfang

18.1.5 Der logische und der visuelle ElementbaumZur nächsten ÜberschriftZur vorigen Überschrift

Erstellen Sie eine Benutzeroberfläche mit der WPF, erzeugen Sie eine Hierarchie ineinander verschachtelter Elemente. Dabei gibt es mit Window immer ein Wurzelelement, in dem die anderen Elemente enthalten sind. Jedes Element kann seinerseits wieder praktisch unbegrenzt untergeordnete Elemente enthalten. Auf diese Weise bildet sich eine durchaus tief gehende Elementstruktur, die als Elementbaum bezeichnet wird. Aufgrund der Architektur der WPF wird zwischen zwei Baumstrukturen unterschieden:

  • logischer Elementbaum
  • visueller Elementbaum

Zur Verdeutlichung der Unterschiede zwischen den genannten beiden Elementbäumen soll der folgende XAML-Code dienen, der innerhalb eines Grid-Controls ein Label- und ein Button-Steuerelement beschreibt.

<Window x:Class="ElementTree.MainWindow" ...>
<Stackpanel>
<Label Content="Label" />
<Button Content="Button" />
</Stackpanel>
</Window>

Der logische Elementbaum wird in diesem XAML-Beispiel durch die Elemente MainWindow, StackPanel, Label und Button gebildet. Er enthält demnach alle Elemente, die in XAML bzw. im Code definiert sind. Grundsätzlich gehören zu einem logischen Baum weder Füllmuster noch Animationen. Jedes WPF-Steuerelement ist selbst durch eine mehr oder weniger große Anzahl visueller Einzelkomponenten aufgebaut. Zum Beispiel besitzt eine Schaltfläche kein fixes Layout, sondern setzt sich aus den Einzelkomponenten ButtonChrome und ContentPresenter zusammen. Alle Einzelkomponenten, die als Basis einer der beiden Klassen

  • System.Windows.Media.Visual oder
  • System.Windows.Media.Media3D.Visual3D

angehören, bilden zusammen den visuellen Elementbaum. Andere Elemente, beispielsweise String-Objekte, gehören nicht zum visuellen Elementbaum, weil sie kein eigenes Renderverhalten benötigen. Zu den Elementen des visuellen Elementbaums hingegen sind die Klassen Button und Label zu zählen. In Abbildung 18.4 ist die Zugehörigkeit der Einzelkomponenten zu den verschiedenen Elementbäumen dargestellt. Die Ausgangsbasis ist hierbei der am Anfang dieses Abschnitts gezeigte XAML-Code.

Abbildung

Abbildung 18.4 Logischer und visueller Elementbaum

Warum wird zwischen den Elementbäumen unterschieden?

WPF-Steuerelemente haben kein eigenes, fixes Layout. Beim Rendern wird der visuelle Elementbaum jeder einzelnen Komponente durchlaufen. Beispielsweise ist der Rahmen einer Schaltfläche zwar Bestandteil der Schaltfläche, kann aber jederzeit durch ein anderes Element ersetzt werden.

Aus der letzten Aussage heraus ergeben sich vielfältige, individuelle Gestaltungsmöglichkeiten.

Infolgedessen kommt es aber auch zu einem Problem hinsichtlich der Auslösung von Ereignissen. Da der Rahmen einer Schaltfläche praktisch beliebig beschrieben werden kann, muss der Button in der Lage sein, zu erkennen, ob er innerhalb oder außerhalb des Rahmens angeklickt wird. Dazu ist ein Ansatz notwendig, der sich am tatsächlichen Layout orientiert. In der WPF werden auch aus diesem Grund die Routed Events beschrieben, die sich nicht am logischen, sondern am visuellen Elementbaum orientieren.

Elementbäume mit Code ermitteln

Sie können den logischen und den virtuellen Elementbaum auch mit Code ermitteln. Dazu stellt Ihnen die WPF mit den beiden Klassen

  • System.Windows.LogicalTreeHelper
  • System.Window.Media.VisualTreeHelper

die benötigten Hilfsmittel zur Verfügung.

Zur Ermittlung der logischen Baumstruktur dient die statische Methode GetChildren der Klasse LogicalTreeHelper. Die Methode erwartet als Argument ein Objekt vom Typ DependencyObject, d. h., das Objekt muss von dieser Klasse abgeleitet sein. Sie übergeben der Methode das Objekt, dessen direkt untergeordnete Elemente Sie ermitteln möchten. Der Rückgabewert ist eine Liste, die in einer Schleife durchlaufen werden kann.

Vom Ansatz her sehr ähnlich ist das Coding der Klasse VisualTreeHelper. Zuerst wird mit der Methode GetChildrenCount ermittelt, aus wie vielen untergeordneten Elementen sich eine Komponente zusammensetzt. Den Rückgabewert können Sie in einer for-Schleife verwenden. Mit der Methode GetChild können Sie auf ein untergeordnetes Element direkt zugreifen.

Das folgende Beispielprogramm soll zeigen, wie Sie beide Klassen und ihre Methoden einsetzen. Dazu sind mit GetLogicalTree und GetVisualTree zwei Methoden codiert, die für das Auswerten des logischen bzw. virtuellen Elementbaums verantwortlich zeichnen. Beide schreiben die spezifische Baumstruktur mit Debug.WriteLine-Anweisungen so in das Ausgabefenster, dass die Hierarchie durch Einrückungen zu erkennen ist.

// Beispiel: ..\Kapitel 18\ElementBaeume
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Debug.WriteLine("");
GetLogicalTree(0, this);
}
protected override void OnContentRendered(EventArgs e) {
base.OnContentRendered(e);
Debug.WriteLine("");
GetVisualTree(0, this);
}
void GetLogicalTree(int depth, object obj) {
Debug.WriteLine(new string('-', depth) + obj);
if (obj is DependencyObject == false) return;
foreach (object child in LogicalTreeHelper.GetChildren(
obj as DependencyObject))
GetLogicalTree(depth + 4, child);
}
void GetVisualTree(int depth, DependencyObject obj) {
Debug.WriteLine(new string('-', depth) + obj.ToString());
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
GetVisualTree(depth + 4, VisualTreeHelper.GetChild(obj, i));
}
}

Der logische Elementbaum kann gezeichnet werden, sobald im Konstruktor das Window mit der Methode InitializeComponent initialisiert worden ist. Der virtuelle Elementbaum kann erst abgefragt werden, wenn das Fenster gerendert worden ist. Das ist der Fall bei der Auslösung des Ereignisses ContentRendered. Um das Ereignis um die Ausgabe im Ausgabefenster zu erweitern, wird die Methode OnContentRendered überschrieben. Sie können den Programmcode in jeder WPF-Anwendung einsetzen, um die Struktur im Fenster Ausgabe zu analysieren.

Abbildung

Abbildung 18.5 Ausgabe des logischen und visuellen Elementbaums



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