GUI-Programmierung 2 - Windows Presentation Foundation (WPF)

Die Seite wird erstellt Henrik Singer
 
WEITER LESEN
GUI-Programmierung 2 - Windows Presentation Foundation (WPF)
GUI-Programmierung 2 - Windows Presentation
                   Foundation (WPF)

                                    Alexander Aumann

                                    aumann@in.tum.de

      Abstract: Seit .NET 3.0 ist WPF als Nachfolger von Windows Forms das Mittel der
      Wahl zum Erstellen grafischer Oberflächen mit .NET. Diese Ausarbeitung stellt die
      Unterschiede und ein paar der interessanteren Features von WPF vor.

WPF wurde mit Version 3.0 des .NET-Frameworks von Microsoft als die neue Programier-
schnittstelle zur Erstellung grafischer Benutzeroberflächen (engl.: graphical user interfaces
= GUIs) eingeführt. Es ist somit der Nachfolger der seit .NET 1.0 verwendeten Windows
Forms, und hat es mittlerweile - was Microsofts eigene Projekte angeht - auch weitge-
hend abgelöst: so ist das neue Visual Studio 2010 mit WPF entwickelt worden [Sch09].
Im Rahmen dieses Dokuments werden daher die Vorzüge des neuen Systems im Vergleich
zu Windows Forms aufgezeigt, sowie einige der interessanteren Neuerungen vorgestellt.

1   Windows Forms oder WPF? Ein Vergleich

Ein erster großer Unterschied zwischen WPF und Windows Forms (kurz: WinForms) ist
die Art und Weise wie das einzelne Standardsteuerelement (zum Beispiel ein Textfeld
oder Button) auf den Bildschirm gezeichnet wird. WinForms greift zur Grafikausgabe auf
GDI/GDI+ zurück und bietet somit praktisch nur eine Einbettung der schon seit Windows
95 grundsätzliche vorhandenen Zeichenfunktionen in Managed Code an. WPF dagegen
zeichnet alle Steuerelemente unter Zuhilfenahme von DirectX selbst. Das ermöglicht auf
der einen Seite eine sehr flexible Anpassung der Steuerelemente (siehe Abschnitt 4: Styles
und Control Templates) und dank DirectX außerdem hardwarebeschleunigtes Zeichnen.
Das zweite große Plus von WPF ist die Art und Weise, wie man als Designer den Aufbau
der grafischen Oberfläche definiert. Betrachten wir dazu kurz die Vorgehensweise unter
WinForms: Selbst wenn man zur Oberflächenerstellung ein grafisches Designprogramm,
wie zum Beispiel den im Visual Studio enthaltenen Designer verwendet, wird der Entwurf
im Hintergrund in C#-Programmcode umgesetzt und die Oberflächendefinition auf diese
Art und Weise festgehalten.
Als WPF-Designer dagegen definiert man Oberflächen in XAML (vergleiche Abschnitt
2) komplett getrennt von der für die Programmlogik verwendeten Programmiersprache.
Dadurch ist es beispielsweise einem unabhängigen Designteam möglich, eine ausgefallene
GUI zu entwerfen, ohne sich Gedanken über die verwendete Programmiersprache machen
zu müssen.
GUI-Programmierung 2 - Windows Presentation Foundation (WPF)
Mit WPF wurden auch viele der im Hintergrund wirksamen Mechanismen überarbeitet,
so wurde das Eventsystem durch Routed Events deutlich verbessert, Commands erlauben
es häufig vorkommende Befehle wie Drucken oder Copy & Paste zentral zu verwalten.
Viele im Verlauf der kommenden Seiten vorgestellte Features funktionieren nur Dank
sogenannter Dependency Properties. All diese Weiterentwicklungen und Neuerungen in
WPF machen es erst so mächtig, wie es letztlich ist. Sie seien hier jedoch nur kurz der
Vollständigkeit halber erwähnt, da eine ausführliche Behandlung den Rahmen dieser Ar-
beit sprengen würde.
Bevor im nächsten Kapitel XAML näher vorgestellt wird, sollen auch einige Nachteile
von WPF im Vergleich zu Windows Forms nicht unerwähnt bleiben. Zum Ersten erfordert
gerade die Tatsache, dass WPF so umfangreiche Möglichkeiten bietet, eine gewisse Einar-
beitungszeit, alleine schon, um sich einen Überblick zu verschaffen. Da WPF im Vergleich
zu WinForms recht jung ist, fehlen auch (noch) ein paar der mächtigeren vorgefertigten
Steuerelemente, wie zum Beispiel die DataGridView.

2     XAML

XAML, beziehungsweise ausgeschrieben die Extensible Application Markup Language,
wurde von Microsoft speziell für WPF entwickelt und ist im wesentlichen ein XML-
Dialekt, der zur Oberflächenbeschreibung (und Ressourcenverwaltung) dient. Zu Ober-
flächenbeschreibung zählen bei WPF nicht nur das einfache Layout beziehungsweise die
Anordnung der Steuerelemente, sondern auch Styles, verschiedene Templates zum noch
feineren Anpassen der einzelnen Steuerelemente und sogar Animationen. Auf diese Fea-
tures wird in den späteren Abschnitten noch ausführlicher eingegangen, in diesem Kapitel
werden zunächst einige Grundlagen vorgestellt.

2.1    XAML-Dateien in einer frischen WPF-Anwendung

Wenn man beispielsweise mit dem Visual Studio 2010 ein neues WPF-Projekt erstellt,
enthält es folgende Dateien, die zur Bearbeitung durch den Entwickler primär vorgesehen
sind:

      • App.xaml
      • App.xaml.cs
      • MainWindow.xaml
      • MainWindow.xaml.cs

Die App.* Dateien sind quasi leer (bis auf die Festlegung des Anwendungshauptfensters
in App.xaml) und dienen später beispielsweise der Definition globaler Ressourcen. Die
Datei MainWindow.xaml sieht zum Beispiel wie folgt aus:
GUI-Programmierung 2 - Windows Presentation Foundation (WPF)
Die erste Zeile legt dabei fest, dass eine Klasse MainWindow im Namespace WpfAppli-
cation1 erstellt werden soll, die von Window erbt.
Die beiden folgenden Zeilen dienen zur Einbindung der für XAML nötigen XML-Namens-
räume, wobei in .../xaml/presentation zum Beispiel alle WPF-Klassen und so-
mit alle Steuerelemente liegen. Dadurch, dass dieser Namensraum direkt dem des aktuel-
len Dokuments zugewiesen wird, können Elemente daraus ohne qualifizierenden Namen
direkt verwendet werden (zum Beispiel Window oder Grid). Im Hintergrund sucht sich der
XAML-Compiler automatisch die korrespondierende .NET-Klasse, im Fall von Window
zum Beispiel System.Windows.Window.
In ../xaml liegen speziellere Elemente, die dazu dienen genauer festzulegen, wie das
XAML-File interpretiert werden soll. Auf diese Elemente kann mit "x:Elementname"
zugreifen.
Was in den verbliebenen Zeilen passiert, wird im nächsten Abschnitt genauer erläutert,
zunächst wollen wir uns kurz der zugehörigen C#-Quelldatei MainWindow.xaml.cs wid-
men. Sie enthält den Teil der Klasse MainWindow, der zur Bearbeitung durch den Pro-
grammierer vorgesehen ist und ist bis auf einen Aufruf der InitializeComponent()-
Methode im Konstruktor anfangs leer. Diese Datei ist später der ideale Ort um beispiels-
weise Code zum Event-Handling et cetera unterzubringen.
Ein großer Unterschied zu WindowsForms ist dabei, dass der automatisch generierte zwei-
te Teil der Klasse MainWindow, der in der Datei MainWindow.d.cs liegt, nur Member-
variablen zuweist, um dem Programmierer die Möglichkeit zu geben auf einzelne Steue-
relemente aus dem Programmcode zuzugreifen. Das Layout hingegen wird darin nicht
festgelegt, sondern zur Laufzeit aus der zugehörigen XAML-Datei konstruiert (genauer
gesagt aus einer zur Kompilierzeit erzeugten binären Repräsentation des XAML-Codes,
sogenanntem Binary-Application-Markup-Language-Code (BAML)).

2.2   Steuerlemente und ihre Eigenschaften

Als Steuerelement (engl.: control) bezeichnet man die einzelnen Bausteine einer GUI,
zum Beispiel Buttons, Labels oder Textfelder. Jedes Steuerelement hat gewisse Eigen-
schaften (engl.: properties), die in WPF in Form von Dependency Properties umgesetzt
werden (eine Erweiterung des Property-Systems von WinForms, mehr sei dazu an dieser
Stelle nicht gesagt). Durch das Setzen dieser Eigenschaften kann man das Verhalten be-
ziehungsweise Aussehen einzelner Steuerelemente beeinflussen, zum Beispiel indem man
die Text-Eigenschaft einer TextBox festlegt.
In XAML werden Eigenschaften festgelegt, indem man im Start-Tag des Elements nach
dem Typ des Elements alle Eigenschaften, die man setzen möchte, aufzählt und ihnen
den entsprechenden Wert zuweist. So erhält die Titel -Eigenschaft des Hauptfensters im
obigen Beispiel den Wert "MainWindow" und zeigt diesen String somit in der Titel-
leiste an, außerdem werden noch Höhe und Breite des Fensters gesetzt (dazu sei kurz
erwähnt, dass WPF aus Flexibilitätsgründen nicht in Pixeln rechnet, sondern in sogenann-
                                               1
ten geräteunabhängigen Einheiten der Größe 96  inch ).
Einem Fenster fügt man Steuerelemente in XAML einfach dadurch hinzu, dass man sie
an der gewünschten Stelle im XML-Baum auflistet, im Regelfall eingebettet in ein Layout
(mehr dazu im nächsten Kapitel). Im Beispiel enthält das Hauptfenster ein Grid-Layout,
welches wiederum einen Button und eine TextBox enthält.
Erwähneswert sind noch sogenannte Attached Properties: Hierbei handelt es sich um Ei-
genschaften, die eigentlich nicht zum Steuerelement selbst gehören, sondern zum Contai-
ner, der es beeinhaltet. Alle Elemente, die in ein Grid eingebettet werden, erhalten so
zum Beispiel eine zusätzliche Row-Eigenschaft. Um diese Attached Properties zu ändern,
muss man vor die Eigenschaft noch den Namen des Elements stellen, zu der sie gehört:
Grid.Row="0" im Beispiel setzt diese Eigenschaft für das Textfeld auf 0.
Nachdem nun ein grober Überblick über XAML erfolgt ist, beschäftigt sich der nächste
Abschnitt näher mit den verschiedenen Möglichkeiten eine Oberfläche zu strukturieren.

3   Layout

Als Layout bezeichnet man allgemein die Anordnung von Steuerelementen auf der Be-
nutzeroberfläche. Interessant wird die Angelegenheit vor allem, wenn beispielsweise der
Benutzer die Fenstergröße ändert oder eine Labelbeschriftung zu groß wird und die Ober-
fläche zur Laufzeit angepasst werden muss, um trotzdem alle Informationen in angemesse-
ner Weise zu repräsentieren. An dieser Stelle kommen die WPF-Layout-Panels ins Spiel.
Sie ermöglichen es Elemente im Fenster relativ zueinander anzuordnen und kümmern
sich zum Beispiel darum, dass wenn sich die Aufschrift eines Labels ändert alle nötigen
Größenverhältnisse der Oberfläche angepasst werden.
Daraus resultierend ist es in WPF nicht üblich einzelne Elemente, wie noch bei Win-
Forms ursprünglich vorgesehen, nach absoluten Koordinaten anzuordnen. Stattdessen ist
der Standardansatz immer die Verwendung eines passenden Layoutpanels. Die folgenden
Abschnitte stellen die verfügbaren Panels jeweils kurz vor.
3.1   Das StackPanel

Das StackPanel ordnet Elemente entweder in einem horizontalen oder vertikalen Stapel
an. Mit der Orientation-Eigenschaft des Stackpanels lässt sich festlegen, ob die Elemen-
te vertikal oder horizontal ausgerichtet werden. Zur Beeinflussung der Anordnung eines
Steuerelements im Beispiel des vertikalen Stapels dient unter anderem die sogenannte
HorizontalAlignment-Eigenschaft des jeweiligen Controls dazu, es links, rechts, zentriert
oder gestreckt auszurichten.

3.2   Das WrapPanel

Ein weiterer Layout-Container ist das sogenannte WrapPanel, dass es ermöglicht Elemen-
te in einer einzigen Reihe anzuordnen, wobei Elemente, die nicht mehr Platz haben, au-
tomatisch in die nächste Reihe umgebrochen werden. Jede Zeile wird dabei groß genug
gemacht, um das höchste Steuerelement aufnehmen zu können, niedrigere Elemente wer-
den entsprechend ihres Alignments darin ausgerichtet.

3.3   Das DockPanel

Das DockPanel ermöglicht es, Elemente an eine der vier Seiten des Containers anzuheften.
Ein Standardbeispiel in einer echten Anwendung wären ToolBox-Leisten, die sich häufig
am oberen oder linken Rand eines Fensters befinden. Mit Hilfe des Attached Properties
Dock des DockPanels, können die einzelnen Steuerelemente entsprechend angeordnet
werden. Hierbei spielt die Reihenfolge der Steuerelemente eine Rolle: Fügt man zuerst
ein Steuerelement ein, das oben andockt, nimmt es die gesamte Breite des Fensters ein.
Danach eingefügte Steuerelemente, die zum Beispiel links angedockt werden, bekommen
den restlichen Platz auf dieser Seite und so weiter.

3.4   Das Grid

Das Grid-Layout ist der mächtigste aller Layout-Container. Er teilt den zu verwaltenden
Platz in Zeilen und Spalten auf und jedem Kindelement können schließlich ein oder meh-
rere Zellen in diesem Gitter zugeordnet werden. Auf diese Art und Weise sind ausgefalle-
ne Layouts möglich, vor allem durch Schachteln von Grids und den einfacheren Layout-
Containern können so nahezu beliebige Anordnungen erreicht werden.
Abbildung 1 zeigt das Layout einer einfachen Beispielanwendung ”Filmsammlung”.
Wie durch die roten Linien angedeutet, besteht das Layout aus einem äußeren 3x3-Grid.
Die gesamte mittlere Spalte wird von einem GridSplitter beansprucht, der es dem Benutzer
ermöglicht das Verhältnis von linker zu rechter Seite zu ändern. Links und rechts des
Abbildung 1: Das Grid-Layout

Splitters sind in der obersten Zeile Labels eingefügt, in der linken Spalte füllt eine ListBox
die verbliebenen zwei Zeilen. Rechts ist unter dem Label ein weiteres Grid eingefügt,
welches die nötigen Textfelder und Labels enthält, darunter befindet sich ein FlowPanel
zur Ausrichtung der beiden Buttons.
So sieht der Anfang einer Grid-Layout-Definition für gewöhnlich in XAML aus:

      ...Steuerelemente...
    
Im Grid.Row(/Column)Definitions-Abschnitt wird die benötigte Zeilen- und
Spaltenzahl festgelegt, die Breite der Spalten (beziehungsweise analog Höhe der Zeilen)
kann auf drei unterschiedliche Arten festgelegt werden: Auto legt fest, dass die Spalte
genau so breit ist, dass alle Elemente Platz haben. Das Zusammenspiel der Breitenanga-
ben 1* und 3* sorgt dafür, dass die dritte Spalte, wenn mehr Platz entsteht (zum Beispiel
durch eine Vergrößerung des Fensters) dreimal so stark wächst wie die erste. Zuletzt gäbe
es die Möglichkeit eine feste Zahl an Einheiten für die Breite anzugeben.
Die einzelnen Kindelemente können mit Hilfe der Attached Properties Row, Column,
RowSpan und ColumnSpan angeordnet werden. Die ersten legen dabei fest welcher Zelle
das Element zugeordnet ist, die anderen beiden, über wie viele Zeilen und Spalten es sich
ausbreitet.

3.5   UniformGrid und Canvas

UniformGrid und Canvas sind spezialisierte Layout-Container, die im Vergleich zu den
bereits erwähnten seltener Verwendung finden. Das UniformGrid teilt ein Gebiet in ein
Raster aus lauter gleich großen Zeilen und Spalten auf, das Canvas dient zur Anordnung
von Elementen nach absoluten Koordinaten, was nur in Spezialfällen (zum Beispiel im
Zusammenhang mit komplexen Animationen) Sinn macht.

4     Styles und Control Templates

Nach den grundsätzlichen Möglichkeiten zur Anordnung von Steuerelementen kommen
wir nun zu den Möglichkeiten, die WPF anbietet um die einzelnen Elemente nahezu be-
liebig anzupassen: Styles und Control Templates. Damit sind umfangreiche Änderungen
möglich, ohne dazu die zugehörige Programmlogik neu schreiben zu müssen.

4.1   Styles

Styles ermöglichen es dem Designer in XAML einzelne Eigenschaften eines Steuerele-
ments zu ändern und dem Element so ein neues Aussehen zu geben. Als Beispiel betrach-
ten wir zunächst einen einfachen Style, der die Schrift eines Labels ändert:
In der ersten Zeile wird dem Style mit x:Key="LabelHeaderStyle" ein Name
zugewiesen. Ansonsten enthält die Styledefinition eine Reihe von sogenannten Settern,
die der Style.Setters-Sammlung hinzugefügt werden. Jeder der Setter enthält ein
Property-Attribut, das festlegt, welche Eigenschaft geändert werden soll und ein Value-
Attribut, das den neuen Wert bestimmt. Dieses kann auch komplex sein, und wird dazu in
ein eigenes Setter.Value-Tag eingebaut. Im Beispiel ist das ein LinearGradientBrush
für die Foreground -Eigenschaft, der einen gleichmäßigen Farbverlauf zwischen den Far-
ben an bestimmten Offsets ermöglicht, in diesem Fall allerdings nur von schwarz über
schwarz nach schwarz. Warum das so Sinn machen kann, dazu gleich mehr.
Zunächst aber zur Frage, wo denn nun der Nutzen von Styles liegt, man könnte die Eigen-
schaften wie Schriftgröße und -farbe schließlich auch direkt in der Oberflächendefinition
des Layouts ändern, was sogar weniger Schreibaufwand verursacht. Der große Vorteil von
Styles ist deren Wiederverwendbarkeit: den einmal definierten Style kann man beliebig
vielen Steuerelementen zuweisen, zum Beispiel allen, die eine Überschrift darstellen. Und
wenn man sich späer zu einer Umgestaltung entschließt, muss man die Änderungen nur an
einer zentralen Stelle - dem Style - vornehmen.
Styles werden als Ressourcen angelegt. Auf das Ressourcenmanagement wird an dieser
Stelle nicht näher eingegangen, näheres dazu findet sich zum Beispiel unter [WEB10a].
Wie weist man nun aber einem Steuerelement einen speziellen Style zu? Dazu gibt es zwei
grundsätzliche Ansätze: die erste Möglichkeit ist, die Style-Eigenschaft des Steuerele-
ments zu setzen:

Auf diese Art und Weise wird der LabelHeaderStyle als Ressource geladen und dem Label
zugewiesen. Die zweite Möglichkeit ist, Styles automatisch allen Elementen eines Typs
zuzuweisen. Dazu muss die TargetType-Eigenschaft gesetzt werden, und der Style darf
keinen Namen erhalten:

      (...)
    
Styles können allerdings mehr als nur einzelne Eigenschaften statisch verändern, sie können
nämlich durch sogenannte Style-Trigger auf verschiedene Events reagieren und auf diese
Art und Weise zum Beispiel einen MouseOver-Effekt erzeugen:

      ...Setter...
...rückgängig machen...
          
      .

Dieser Style enthält einen EventTrigger der ausgelöst wird, sobald der Mauszeiger über
dem Steuerelement ist. Als ausgeführte Aktion wird eine Animation festgelegt (in XAML
sind Animationen immer in ein Storyboard eingebettet), die die Farbe des mittleren Offset
(vom ursprünglichen Schwarz) in 0.5 Sekunden nach BurlyWood ändert. Dadurch lässt
sich eine Art Aufglüheffekt erzeugen. Um diesen (dauerhaften) Effekt wieder rückgängig
zu machen, ist es sinnvoll auch den MouseLeave-Event zu behandeln.
Styles bieten bereits vielfältige Möglichkeiten zur Anpassung einzelner Controls. Will
man ein Steuerelement jedoch komplett umgestalten und nicht nur einzelne Eigenschaf-
ten ändern, greift man auf Control Templates zurück, die im nächsten Kapitel vorgestellt
werden.

4.2   Control Templates

In WPF sind alle Steuerelemente intern aus kleineren Teilelementen zusammengesetzt,
so besteht ein Button aus einem Rahmen, in den ein ContentPresenter eingebettet ist, der
die Aufschrift darstellt. Dieser interne Zusammenbau wird im Gegensatz zum logischen
Aufbau einer Oberfläche (ein Fenster enthält ein Layout, welches Steuerelemente enthält)
als Visual Tree bezeichnet (näheres dazu zum Beispiel hier: [Sam10]).
Möchte man ein Steuerelement also grundlegend umbauen muss es eine Möglichkeit ge-
ben diesen Visual Tree zu verändern. Control Templates bieten diese und wir werden sie
im Folgenden benutzen um den Standardbutton anzupassen. Konkret soll der Button deut-
lich abgerundete Ecken erhalten sowie eine andere Rahmen- und Hintergrundfarbe, die
sich dynamisch anpasst: So soll zum Beispiel ein Button über dem der Mauszeiger ist
dunkler werden und auch auf Klicks optisch reagieren.
Das nötige Control Template sieht wie folgt aus:
...beliebige (Style)Setter möglich...
      
               ... 
               ... 
              
                      ...MouseOver-Aussehen festlegen...
                  
                      ... "Disabled" und "Pressed"...
                
              ...auch Trigger möglich...
            
Das erste, was hierbei vielleicht auffällt ist, dass das Control Template in einen Style ein-
gebettet ist. Das ist gängige Praxis und ermöglicht vor allem eine automatische Template-
Zuweisung an alle Buttons (TargetType-Eigenschaft des Styles). Das neue Control Tem-
plate wird der Template-Eigenschaft des Steuerelements zugewiesen. Im tatsächlichen
Control Template wird nun der Aufbau des Buttons festgelegt, in diesem Fall genügt uns
ein Rahmen mit abgerundeter Ecke und den entsprechenden Farbeigenschaften. Der Rah-
men enthält wiederum einen ContentPresenter und außerdem einen VisualStateManager,
dazu gleich mehr.
Sogenannte Template Bindings erlauben es eine interne Eigenschaft, wie zum Beispiel die
TextBlock.Foreground -Eigenschaft an die externe Eigenschaft Foreground des Buttons zu
binden: das bedeutet, wenn der Designer in XAML dem Button einen anderen Vordergrund
zuweist, wird diese Zuweisung an den TextBlock weitergeleitet.
Der VisualStateManager schließlich bietet eine einfache Möglichkeit für einzelne Zustände
wie MouseOver oder Clicked entsprechende Eigenschaften zu setzen, über Transitions
können die Übergänge zwischen diesen Zuständen feiner geregelt werden. Im Beispiel
sollen die Übergänge zwischen den einzelnen Zuständen jeweils eine halbe Sekunde dau-
ern, außer bei einem Klick (To:Pressed ), der sofort angezeigt wird.
Abbildung 2 zeigt die angepasste Benutzeroberfläche mit Überschriftlabels und neuen
Buttons, sowie einem angepassten Hintergrund mit Farbverlauf und leicht durchsichtigen
Textfeldern.

                  Abbildung 2: Filmsammlung mit benutzerdefiniertem Style

Zum Abschluss bleibt noch zu sagen, dass das Buttonbeispiel noch ein recht einfaches
Control Template ist, da ein Button prinzipiell nur eine logische Funktion hat. Möchte
man dagegen zum Beispiel eine ScrollBar umgestalten muss man deutlich mehr beachten,
da sie aus mehreren Komponenten, wie einem Balken, einem Slider und den Pfeiltas-
ten zusammengesetzt ist und somit von der Anwendungslogik gewisse Vorgaben an ein
eigenes Control Template gestellt werden. Ein sehr guter Einstiegspunkt für eigene Tem-
plates ist das Microsoft SimpleStyles-Beispielprojekt, das für jedes Standardcontrol ein
übersichtliches, angepasstes Control Template enthält. Das Beispiel steht hier zum Down-
load bereit: [WEB10b].
5     Data Binding und Data Templates

Nachdem wir nun schon gesehen haben was WPF im Gegensatz zu Windows Forms in
Sachen Oberflächenanpassung alles kann, soll nun auch noch ein Blick auf Datenbindung
in WPF geworfen werden. Datenbindung ist ein recht weitläufiger Begriff, im aktuellen
Zusammenhang bedeutet es so viel wie irgendeine Art von Daten an ein Steuerelement
auf der Benutzeroberfläche zu binden.

5.1   Data Binding

Die einfachste Art von Data Binding in WPF wäre es beispielsweise eine bestimmte (De-
pendency) Property eines Controls an eine andere Eigenschaft eines zweiten Controls zu
binden. So ist es zum Beispiel möglich ein Slider-Control mit der Schriftgröße eines La-
bels so zu verknüpfen, dass sich die Schriftgröße des Labels automatisch ändert, sobald
der Benutzer den Slider bewegt.
Die interessantere Art der Datenbindung ist es, im Hintergrund von der Programmlogik ge-
speicherte Daten mit einem oder mehreren Steuerelementen zu verknüpfen. Hierzu wollen
wir uns die Filmsammlung noch einmal ansehen und konkret die Textfelder auf der rechten
Seite mit den richtigen Werten füllen, je nachdem, welcher Film in der ListBox ausgewählt
wurde. Das funktioniert in WPF überraschend einfach, wie im Folgenden dargestellt wird.
Die Anwendung soll im Hintergrund Film-Objekte bereitstellen, die alle für einen einzel-
nen Film nötigen Daten kapseln. In diesem einfachen Beispiel seien das fullName, short-
Name, producers, director, writers, year und number. Um eine Datenbindung zu einem
Film-Objekt nutzen zu können, müssen all diese Eigenschaften als public property
zur Verfügung gestellt werden, der nötige C#-Code sieht wie folgt aus:

      namespace VideoLibrary
      {
        class Film
        {
          private string fullName;
          public string FullName
          {
            get { return fullName; } set { fullName = value;}
          }
          //... restliche Properties (shortName, director...)
        }
      }

Diese Daten sind zum Beispiel in einer Datenbank abgelegt, die Zugriffsfunkionalität da-
rauf sei in einer Klasse DataStore abgelegt. Um sie nun mit der Oberfläche zu verknüpfen
muss in der MainWindow-Klasse noch ein wenig Code geschrieben werden:
public partial class MainWindow : Window
    {
        DataStore ds;
        List films;
        public MainWindow()
        {
            InitializeComponent();
            ds = new DataStore();
            films = ds.GetFilms();
            listBoxFilms.ItemsSource = films;
        }
    }

Das DataStore-Objekt liefert eine Liste von Filmen zurück, die der ListBox als Datenquel-
le zugewiesen wird.
Als nächstes wird in XAML eine DataBinding-Verknüpfung festgelegt, um die Textfelder
mit der jeweiligen Filmeigenschaft zu verknüpfen:

Anstatt also der Texteigenschaft einen statischen String zuzuweisen wird festgelegt, dass
sie mit dem FullName-Property der aktuellen Datenquelle verbunden werden soll. Bleibt
zu guter Letzt noch das Setzen der Datenquelle. Das ginge entweder über die Angabe
einer Quelle im Binding-Ausdruck, oder aber über einen DataContext. Der große Vorteil
des DataContext ist, dass Kindelemente (zum Beispiel in einem Grid), die selber keinen
DataContext festlegen, automatisch im Kontext des Containers stehen. Kurz: durch setzen
eines DataContext für das Grid, haben alle Textfelder die richtige Datenquelle:

    (...)
    
Das war auch schon alles: wenn nun der Benutzer in der Liste einen Film auswählt, werden
die Textfelder mit den richtigen Werten gefüllt. Und es geht noch mehr: alle Änderungen,
die an den Texten vorgenommen werden, werden automatisch in die Filmliste im Hinter-
grund übernommen. Das einzige Problem ist noch, dass die Liste selbst nicht weiß, wie
sie ein Film-Objekt darstellen soll, sie ruft deshalb einfach auf jedes einzelne Objekt die
.ToString()-Methode auf, und zeigt jeweils nur VideoLibrary.Film an. Eine erste
Abhilfe wäre es diese Methode für die Film-Klasse zu überschreiben. WPF bietet jedoch
mit sogennanten Data Templates ein deutlich mächtigeres Werkzeug für diese Aufgabe.

5.2   Data Templates

Mit Data Templates lässt sich für das einzelne Item einer Liste (oder auch eines TreeViews)
ganz detailliert der Aufbau festlegen. Im Rahmen eines einfachen Beispiels soll dazu in
der Liste von jedem Film der Kurzname und leicht eingerückt der Regisseur dargestellt
werden, eingebettet in einen hübschen Rahmen. Das Template in XAML sieht wie folgt
aus:

              (...Grid.Row Definitionen...)
              
Es werden die zwei nötigen Textfelder mit Hilfe eines Grids in den Rahmen eingebettet.
Die Text-Eigenschaft wird jeweils an die entsprechende Filmeigenschaft gebunden, nur so
kann jedes Listenelement die richtigen Daten anzeigen. Abschließend muss der ListBox
nun noch dieses Data Template zugewiesen werden:

Als Ergebnis erhalten wir nun also eine vollständige, editierbare Filmauflistung, wie in
Abbildung 3 dargestellt.

6     Zusammenfassung

Die im Rahmen dieser Arbeit vorgestellten Features sollen einen ersten Überblick darüber
geben, welche Möglichkeiten WPF im Vergleich zu WinForms bietet und als Anregungung
Abbildung 3: Filmsammlung mit überarbeiteter Liste

zu eigenen Experimenten dienen. Eine halbwegs vollständige und tiefgehende Abhand-
lung von WPF ist an dieser Stelle nicht möglich und würde Bücher füllen. Hier verweise
ich deshalb auf die angegebene Literatur (hauptsächlich [Mac97]) und Recherche im In-
ternet und hoffe, dass ich zumindest ein wenig das Interesse an der Windows Presentation
Foundation wecken konnte.

7   Literaturverzeichnis

Literatur

[Mac97]    Matthew MacDonald. Pro WPF in C#2008. Apress, 1997.

[Sam10]    Jitendra Sampathirao. Logical Tree and Visual Tree in WPF.
           http://www.c-sharpcorner.com/UploadFile/jitendra1987/4046/
           Default.aspx, Stand: 15.12. 2010.

[Sch09]    Holger Schwichtenberg. Microsofts Visual Studio 2010 Beta 2 - eine Querschau.
           http://www.heise.de/developer/artikel/
           Microsofts-Visual-Studio-2010-Beta-2-eine-Querschau-868144.
           html, 12 2009.

[WEB10a] WEBSITE. Resources Overview.
         http://msdn.microsoft.com/en-us/library/ms750613.aspx, Stand:
         15.12. 2010.

[WEB10b] WEBSITE. WPF Documentation Samples. http://code.msdn.microsoft.
         com/wpfsamples\#controlcustomization, Stand: 15.12. 2010.
Sie können auch lesen