7201.book Seite 30 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 31 Donnerstag, 5. September 2019 8:43 08
0Hinweise zum Buch
Bevor es losgeht, finden Sie hier noch ein paar Hinweise dazu, wie Sie am bes- ten mit diesem Buch arbeiten. Auf den folgenden Seiten finden Sie kurze Inhaltsangaben zu allen Kapiteln und Informationen zu den verwendeten Beispielen: wo Sie diese finden und welche Systemvoraussetzungen not- wendig sind, um sie nachzuvollziehen.
Für wen ist dieses Buch gedacht?
Um den meisten Nutzen aus diesem Buch zu ziehen, sollten Sie über eine gute Portion an C#-Know-how und über etwas Wissen rund um .NET verfügen. Fragen zu Events, Delegates, anonymen Methoden, Lambda Expressions, Auto-implemented Properties, async und await sollten Sie nicht gleich in Verlegenheit bringen. Sind Sie beim Thema .NET oder C# etwas un- sicher, empfehle ich Ihnen, vorab ein C#-Buch zu lesen. Grundkenntnisse in XML sind für das vorliegende Buch von Vorteil, allerdings nicht zwingend erforderlich. Das Buch richtet sich an .NET-Entwickler, die Desktop-Anwendungen für Windows mit der Windows Presentation Foundation umsetzen möchten. Es eignet sich sowohl für WPF-Ein- steiger als auch für leicht fortgeschrittene WPF-Entwickler. Seit Windows 10 lassen sich neben der klassischen Desktop-Anwendung auch die Universal Windows Apps entwickeln. WPF-Anwendungen funktionieren im Gegensatz zu den Univer- sal Windows Apps auch unter älteren Windows-Versionen. Allerdings lassen sich WPF- Anwendungen nur auf dem Desktop von Windows ausführen. Die Universal Windows Apps laufen dagegen neben dem Desktop auf verschiedensten Umgebungen: Xbox, HoloLens oder sogar auf dem Raspberry Pi. Doch wenn Universal Windows Apps auch auf dem Desktop laufen, warum sollten Sie dann die WPF einsetzen? Die WPF ist den Universal Windows Apps nach wie vor in einigen Teilen überlegen, da das Framework deutlich mehr Möglichkeiten bietet. Somit werden auch heute mächtige Geschäftsanwendungen, die als lokale Applikation unter Windows laufen sollen, mit der WPF umgesetzt. Beispielsweise ist Visual Studio 2019 eine WPF-Anwendung, und die typische datenzentrische Geschäftsanwendung wird es auch sein. Wenn Sie also eine Anwendung für den Desktop bauen möchten, sind Sie hier genau richtig. Möchten Sie stattdessen lieber eine Universal Windows App entwickeln, in der Sie wie auch bei der WPF XAML und C# einsetzen können, sind Sie hier auch nicht falsch, da viele Konzep- te gleich sind. Zudem finden Sie im letzten Kapitel dieses Buchs eine Einführung in die Ent- wicklung von Universal Windows Apps.
31 7201.book Seite 32 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 33 Donnerstag, 5. September 2019 8:43 08
Hinweise zum Buch Der Aufbau des Buches
Im vorliegenden Buch erhalten Sie neben dem Wissen, das Sie zum Entwickeln einer WPF- teren lässt sich das Aussehen von Controls neu definieren. In dieser Gruppe erfahren Sie Anwendung benötigen, reichlich Hintergrundinformationen über die Konzepte der WPF: auch, wie die WPF mit Daten umgeht. In diesem Zusammenhang gehe ich speziell auf das Dazu gehören unter anderem die Extensible Application Markup Language (XAML), Depend- Data Binding ein. ency Properties, Routed Events, Commands, Ressourcen oder Logical und Visual Trees. Für – Kapitel 10: Ressourcen einfache Applikationen ist die Kenntnis dieser Konzepte nicht immer erforderlich, für die – Kapitel 11: Styles, Trigger und Templates Entwicklung Ihrer umfangreichen Wunschanwendung ist sie allerdings eine wichtige Vo- – Kapitel 12: Daten raussetzung. Erst mit diesen Konzepten im Hinterkopf werden Sie in der Lage sein, mit der WPF erfolgreich komplexe Anwendungen zu entwickeln. III. Reichhaltige Medien und eigene Controls In Teil III lernen Sie, wie Sie mit der WPF 2D- und 3D-Grafiken darstellen und auch dyna- Das vorliegende Buch richtet sich also an Entwickler und nicht an grafische Designer. Ein De- misch erzeugen. Sie lernen hier alles, was Sie über das in die WPF integrierte Animations- signer kann mithilfe dieses Buchs zwar den XAML-Code nachvollziehen, den seine Tools wie system, über die Audio/Video-Unterstützung und über Texte und Dokumente wissen Blend generieren, aber eben nur dann, wenn er auch die Grundlagen der .NET-Programmie- müssen. Die Dokumente in der WPF sind gleichzeitig auch der Schlüssel zum Drucken. rung und C# beherrscht. Haben Sie Webseiten entwickelt und dazu Tools wie FrontPage oder Sie lernen aber nicht nur die Medien kennen, sondern erfahren auch, wie Sie eigene Con- Dreamweaver eingesetzt, werden Sie bestimmt die Erfahrung gemacht haben, dass für kom- trols entwickeln. plexere Fälle das Programm nicht den gewünschten Output liefert und Sie das HTML-Doku- – Kapitel 13: 2D-Grafik ment manuell editieren müssen. Ebenso verhält es sich mit XAML. Obwohl es viele Tools gibt, die XAML generieren, werden Sie bestimmte Dinge in XAML weiterhin »von Hand« er- – Kapitel 14: 3D-Grafik stellen oder zumindest anpassen müssen, um zu Ihrem Ziel zu kommen. – Kapitel 15: Animationen – Kapitel 16: Audio und Video – Kapitel 17: Eigene Controls Der Aufbau des Buches – Kapitel 18: Text und Dokumente Das Buch besteht aus 21 Kapiteln, die sich in vier Teile gruppieren lassen: IV. Interoperabilität und Apps I. WPF-Grundlagen und Konzepte In Teil IV erfahren Sie, wie Sie in Ihrer WPF-Anwendung einen SaveFileDialog nutzen, In Teil I lernen Sie die Grundlagen der WPF kennen. Dazu gehören die wichtigsten Klas- Ihre Anwendung automatisieren und verteilen und wie Sie die Möglichkeiten der Win- sen, XAML, Controls, Layout und Konzepte der WPF, wie Dependency Properties, Routed dows Taskbar in Ihrer Applikation nutzen. Sie lernen auch, wie Sie in Ihrer WPF-An- Events oder Commands. wendung alte Technologien mittels Interoperabilität einbinden. Zudem erhalten Sie in Teil IV eine Einführung in die Entwicklung von Universal Windows Apps in Windows 10. – Kapitel 1: Einführung in die WPF – Kapitel 19: Standard-Dialoge, Windows Taskbar und mehr – Kapitel 2: Das Programmiermodell – Kapitel 20: Interoperabilität – Kapitel 3: XAML – Kapitel 21: Universal Windows Apps und WinUI – Kapitel 4: Der Logical und der Visual Tree – Kapitel 5: Controls –Kapitel 6: Layout Der Inhalt der einzelnen Kapitel – Kapitel 7: Dependency Properties ̈ Kapitel 1, »Einführung in die WPF« – Kapitel 8: Routed Events Wir beginnen mit einem Überblick über die WPF. Sie erfahren, wie sich die WPF ins .NET Framework eingliedert. Nach einem Blick auf die Geschichte der Windows-Programmie- – Kapitel 9: Commands rung lernen Sie die technische Architektur der WPF kennen und bekommen einen ersten II. Fortgeschrittene Techniken Einblick in WPF-Konzepte wie XAML, Dependency Properties, Routed Events und Com- Fortgeschrittene Techniken werden in Kapitel 10 bis Kapitel 12 betrachtet. Dazu gehören mands. neben Ressourcen die in der WPF existierenden Styles, Trigger und Templates. Mit Letz-
32 33 7201.book Seite 34 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 35 Donnerstag, 5. September 2019 8:43 08
Hinweise zum Buch Der Aufbau des Buches
̈ Kapitel 2, »Das Programmiermodell« kennen. Außerdem betrachten wir hier das Model-View-ViewModel-Pattern (MVVM), das Die WPF besitzt eine tief verschachtelte Klassenhierarchie. Hier lernen Sie die zentralen auf der Logik von Commands basiert. Klassen kennen. Sie erhalten in diesem Kapitel eine Übersicht über die Projektvorlagen in ̈ Kapitel 10, »Ressourcen« Visual Studio 2019, bevor wir die ersten WPF-Anwendungen mit speziellem Fokus auf den Dieses Kapitel zeigt Ihnen die Funktionsweise der WPF-spezifischen logischen Ressour- Klassen Application, Dispatcher und Window entwickeln. cen. In ihm gehe ich auch auf die bereits aus älteren .NET-Versionen bekannten binären ̈ Kapitel 3, »XAML« Ressourcen ein. Zudem lernen Sie hier, wie Sie auf einfache Weise einen Splashscreen er- Kernpunkt dieses Kapitels ist die in der WPF zum Beschreiben von Benutzeroberflächen stellen. eingesetzte XML-basierte Beschreibungssprache Extensible Application Markup Language ̈ Kapitel 11, »Styles, Trigger und Templates« (XAML). Hier lernen Sie die Syntax von XAML sowie zahlreiche Tipps und Tricks kennen. Styles werden in der WPF eingesetzt, um Werte für mehrere Properties zu definieren. ̈ Kapitel 4, »Der Logical und der Visual Tree« Diese »Wertesammlung« lässt sich dann auf mehreren Elementen setzen. Templates die- Wenn Sie eine Benutzeroberfläche in der WPF entwickeln, bauen Sie im Grunde eine nen dazu, das Aussehen für ein Control oder für Daten zu definieren. In einem Style wie Hierarchie von Objekten auf. Ein Window enthält einen Button, ein Button enthält einen auch in einem Template lassen sich Trigger erstellen, die sich beispielsweise für Mouse- String usw. Die WPF kennt zur Laufzeit zwei Hierarchien, die Voraussetzung für viele Over-Effekte verwenden lassen. Dieses Kapitel gibt Ihnen einen gründlichen Einblick in Funktionen der WPF sind, wie Routed Events und Ressourcen. Dieses Kapitel liefert reich- die Möglichkeiten mit Styles, Triggern und Templates. Dabei gehe ich auch auf den Visual- lich Informationen über die Funktionsweise der beiden Hierarchien und zeigt mit einer StateManager ein, der in .NET 4.0 eingeführt wurde. Subklasse von FrameworkElement, wie die WPF die Hierarchien aufbaut. ̈ Kapitel 12, »Daten« ̈ Kapitel 5, »Controls« Alles Wissenswerte zum Data Binding lesen Sie in diesem Kapitel. Darüber hinaus geht Wie für ein UI-Framework üblich, enthält auch die WPF eine Vielzahl von bereits vordefi- dieses Kapitel auf CollectionViews ein und zeigt, wie Sie bei der WPF durch Ihre Daten na- nierten Controls. Dieses Kapitel zeigt Ihnen die wichtigsten dieser Controls, wie TextBox, vigieren. Sie lernen, Daten zu gruppieren, zu sortieren, zu filtern und zu validieren. Ein Menu, Button, TreeView, ComboBox und ListView. Überblick über das DataGrid bringt Ihnen die zentralen Funktionen dieses Controls zum ̈ Kapitel 6, »Layout« Darstellen von Listen näher. Das Anordnen und Positionieren von Elementen auf der Benutzeroberfläche unterliegt ̈ Kapitel 13, »2D-Grafik« bei der WPF dem sogenannten Layoutprozess. Dieses Kapitel verrät, was sich hinter dem In diesem Kapitel erfahren Sie alles über das »Zeichnen« mit der WPF. Sie erhalten Infor- Layoutprozess verbirgt, und geht speziell auf die Größe von Elementen, den Rand, die mationen über Brushes, Shapes und Drawings. Zudem zeige ich hier, wie Sie Elemente mit Ausrichtung, Transformationen und Layout-Panels ein. Mit dem in diesem Kapitel ver- Effekten ausstatten – die sogenannten Pixelshader –, damit diese beispielsweise einen Pro- mittelten Wissen sind Sie in der Lage, ein pinnbares, animiertes Fenster ähnlich dem Schatten werfen. jektmappen-Explorer in Visual Studio zu implementieren. ̈ Kapitel 14, »3D-Grafik« ̈ Kapitel 7, »Dependency Properties« Dieses Kapitel führt Sie in die 3D-Programmierung mit der WPF ein und bringt Ihnen die Dependency Properties erweitern die klassischen .NET-Properties um WPF-spezifische Lo- dazu notwendigen Grundlagen näher, wie das 3D-Koordinatensystem, das Viewport3D-Ele- gik. Sie sind die Grundlage für Animationen, Styles oder Data Bindings. Was Dependency ment, Kameras und 3D-Modelle. Sie lernen auch, wie Sie Ihre 3D-Inhalte interaktiv gestal- Properties genau sind, wozu sie benötigt werden und wie Sie Dependency Properties nut- ten. zen und implementieren, ist Thema dieses Kapitels. ̈ Kapitel 15, »Animationen« ̈ Kapitel 8, »Routed Events« Die WPF besitzt eine integrierte Unterstützung für Animationen. In diesem Kapitel erfah- Die Events der WPF treten meist als sogenannte Routed Events auf. In diesem Kapitel wird ren Sie alles Notwendige über Timelines, Storyboards, einfache Animationen, Keyframe- gezeigt, wie Routed Events genau funktionieren und wie Sie eigene Routed Events imple- und Pfad-Animationen und über die Animation Easing Functions. mentieren. Darüber hinaus gehe ich auf Maus-, Tastatur-, Stift- und Touch-Events ein. ̈ Kapitel 16, »Audio und Video« ̈ Kapitel 9, »Commands« Integrierte Audio- und Video-Unterstützung ist eine der Stärken der WPF. Dieses Kapitel Commands sind insbesondere dann sinnvoll, wenn Sie mit mehreren Elementen (Button, zeigt, wie Sie unter anderem Videos in Ihre Anwendung einbinden und sie zudem noch MenuItem etc.) einen Befehl auslösen möchten. Neben dem Implementieren von eigenen steuern. Commands lernen Sie in diesem Kapitel die in der WPF bereits vorhandenen Commands
34 35 7201.book Seite 36 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 37 Donnerstag, 5. September 2019 8:43 08
Hinweise zum Buch Wie Sie das Buch lesen
̈ Kapitel 17, »Eigene Controls« Visual Studio bietet Ihnen zum Erstellen von Controls zwei Projektvorlagen: eine für User Hinweis Controls und eine für Custom Controls. Wie Sie ein User Control und ein Custom Control Das Buch verwendet aus didaktischen Gründen an manchen Stellen bewusst Wiederholun- entwickeln, erfahren Sie hier. gen. So erhalten Sie beispielsweise im ersten Kapitel einen Überblick über die WPF-Konzepte. ̈ Kapitel 18, »Text und Dokumente« In späteren Kapiteln werden diese Konzepte wiederholt und vertieft. Reichhaltige Funktionalität bietet die WPF im Zusammenhang mit Text und Dokumen- ten. Was Flow-, Fix- und XPS-Dokumente sind und wie Sie diese Dokumente in Ihrer An- wendung erstellen oder darstellen, ist der Inhalt dieses Kapitels. Dokumente sind auch Systemvoraussetzungen der Schlüssel zum Drucken. Sie erfahren hier also auch, wie Sie aus Ihrer WPF-Anwendung Alle Beispiele in diesem Buch wurden mit der finalen Version von Visual Studio 2019 unter etwas ausdrucken können. Windows 10 entwickelt. Dabei habe ich die frei erhältliche Edition namens Visual Studio ̈ Kapitel 19, »Standard-Dialoge, Windows Taskbar und mehr« Community genutzt, die Sie unter www.visualstudio.com/downloads herunterladen können. Sie lernen hier die Standard-Dialoge zum Speichern und Öffnen von Dateien kennen. Die Beispiele wurden mit .NET Core 3.0 entwickelt. Damit Sie also sofort loslegen und einige Ebenso erfahren Sie, wie Sie Ihre Windows-Anwendung in die Taskbar von Windows 10 in- Beispiele ausprobieren können, sollten Sie auf Ihrem Rechner Folgendes installieren: tegrieren. In diesem Kapitel erkläre ich auch, welche Möglichkeiten Sie haben, um Ihre WPF-Anwendung zu verteilen. ̈ als Betriebssystem mindestens Windows 7 oder am besten Windows 10 ̈ Kapitel 20, »Interoperabilität« ̈ als Entwicklungsumgebung eine Edition von Visual Studio 2019 In diesem Kapitel erfahren Sie, wie Sie die WPF mit Windows Forms, ActiveX, Win32 oder ̈ .NET Framework 4.8 oder .NET Core 3.0 Direct3D kombinieren. Sie erhalten einen Überblick über mögliche Migrationsstrategien Um die Beispiele aus Kapitel 21, »Universal Windows Apps und WinUI«, ausprobieren zu kön- Ihrer Altanwendungen und erfahren anhand zahlreicher Beispiele, wie Sie verschiedene nen, benötigen Sie zwingend Windows 10. Für alle anderen Kapitel reicht eine Windows-Ver- Interoperabilitätsszenarien implementieren. sion ab Windows 7 aus. ̈ Kapitel 21, »Universal Windows Apps und WinUI« Unter Windows 10 lassen sich die sogenannten Universal Windows Apps entwickeln. Das sind native Apps, die C# und XAML und damit viele Konzepte aus der WPF nutzen. In die- Codebeispiele sem Kapitel erhalten Sie eine Einführung in die Entwicklung von Universal Windows Apps Die Codebeispiele zu diesem Buch können Sie in Form der Beispiele.zip-Datei unter folgen- und in das WinUI Framework. dem Link herunterladen: www.thomasclaudiushuber.com/wpfcode Wie Sie das Buch lesen Beispiele zu einem Kapitel Dieses Buch ist so aufgebaut, dass Sie bei Kapitel 1 beginnen und sich von dort Schritt für Die Beispiele.zip-Datei enthält eine nach Kapiteln aufgebaute Ordnerstruktur. Das bedeutet, Schritt zu Kapitel 21 vorarbeiten können. Am Ende jedes Kapitels folgt eine Zusammenfas- Sie finden für jedes Kapitel einen Ordner: K01, K02, K03 usw. Die Beispiele für Kapitel 5, »Con- sung der wichtigsten Punkte. An diesem Überblick können Sie kontrollieren, ob Sie die wich- trols«, liegen im Ordner K05. Unter den Codeausschnitten in diesem Buch finden Sie eine tigsten Inhalte eines Kapitels aufgenommen haben. Unterschrift mit dem Pfad zu der Datei, die den dargestellten Code enthält. Das Folgende ist Falls Sie nicht zu den Lesern gehören, die Bücher von vorn nach hinten durcharbeiten, kön- ein Codeausschnitt aus Kapitel 5, »Controls«; beachten Sie die Unterschrift: nen Sie sich natürlich auch einzelne Kapitel herauspicken und diese als Nachschlagelektüre hängig voneinander zu gestalten. Allerdings sollten einzelne Kapitel auch nicht immer alles
36 37 7201.book Seite 38 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 39 Donnerstag, 5. September 2019 8:43 08
Hinweise zum Buch Wie Sie das Buch lesen
Den Code aus diesem Listing finden Sie, wie in der Unterschrift angegeben, in der Datei Code unwichtig ist. Wie im vorherigen Abschnitt bereits erwähnt, werden die meisten Code- 05 LabelTarget.xaml im Ordner K05. beispiele in diesem Buch mit einer Unterschrift versehen. Die Unterschrift enthält entweder einen Pfad zur Quelldatei oder eine kurze Beschreibung des dargestellten Codes. Sehr kurze, Quellcode zu Abbildungen selbsterklärende Codebeispiele besitzen keine Unterschrift. In diesem Buch befinden sich auch Abbildungen, zu denen der Code nicht explizit abgebildet Einige Listings in diesem Buch besitzen Zeilennummern. Diese gehören nicht zum eigent- ist, da es beispielsweise an der entsprechenden Stelle für den dargestellten Sachverhalt nicht lichen Quellcode, sondern dienen einfach als zusätzliches Beschreibungsmittel. In Kapitel 4, erforderlich ist. Dennoch finden Sie in der Beispiele.zip-Datei im Ordner eines Kapitels oft »Der Logical und der Visual Tree«, finden Sie ein solches Listing mit Zeilenangabe. Im Buch- auch jenen Code, der diesen Abbildungen zugrunde liegt. Im Ordner K05 gibt es unter ande- text wird dann auf eine Listingzeile beispielsweise mit »Beachten Sie in Listing 2 in Zeile 8 …« rem eine Datei Abbildung 5.14 – ScrollViewer.xaml, die den für Abbildung 5.14 verwendeten hingewiesen. Code enthält, der im Buch nicht explizit dargestellt ist. 1
38 39 7201.book Seite 40 Donnerstag, 5. September 2019 8:43 08
Hinweise zum Buch
Achtung Dieser Kasten weist Sie explizit auf ein eventuell auftretendes Problem, mögliche Stolperfal- len oder etwas extrem Wichtiges hin.
Hinweis Ein Hinweis-Kasten hebt wichtige Details hervor oder erläutert einen Sachverhalt noch etwas tiefgründiger.
Etwas zu Anglizismen »Kommen Sie zu uns ins Office in unserer neuen Location in...«, warum nicht einfach Büro und Standort statt Office und Location? Ich bin wirklich kein Fan von Anglizismen. Allerdings ist es für einige Begriffe in diesem Fachbuch meines Erachtens wenig sinnvoll, sie ins Deut- sche zu übertragen. Dieses Buch verwendet daher an vielen Stellen durchgängig die eng- lischen Originalwörter und -begriffe. Ich habe mich dafür entschieden, da einerseits eine deutsche Variante eines Begriffs oft zu Missverständnissen führt und es andererseits in der WPF Begriffe wie beispielsweise Dependency Properties gibt, für die in der Entwicklerszene einfach kein konsistentes deutsches Pendant existiert. Deutschsprachige WPF-Entwickler sagen daher ebenfalls »Dependency Properties« und nicht »Abhängigkeitseigenschaften« (auch wenn die Dependency Properties in der deutschen MSDN-Dokumentation als Abhän- gigkeitseigenschaften bezeichnet werden). Aufgrund dieser Tatsache finden Sie in diesem Buch die original englischen Begriffe wie De- pendency Properties, Routed Events, Commands, Markup Extensions etc. Diese Begriffe gehen meist mit den Klassennamen einher, die für die entsprechende Funktionalität verwendet werden. Für Dependency Properties haben Sie die Klassen DependencyObject und Dependen- cyProperty, für Routed Events die Klasse RoutedEvent usw. Auch Steuerelemente werden durchgängig als »Controls« bezeichnet, die .NET-Eigenschaf- ten eines Objekts als »Properties« oder die Behandlungsmethoden für ein Event als »Event Handler«.
40 7201.book Seite 42 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 43 Donnerstag, 5. September 2019 8:43 08
Kapitel 1 1 Einführung in die WPF
Lehnen Sie sich zurück. In diesem Kapitel werden Sie »gebootet«. Nach einem Blick auf die WPF im .NET Framework und einem Schnelldurchlauf durch die Windows-Programmiergeschichte erfahren Sie mehr über die Architektur und Konzepte der WPF.
Die Windows Presentation Foundation (WPF) ist Teil des .NET Frameworks seit der Version 3.0 und Teil von .NET Core seit Version 3.0. Wie sich die WPF in die Struktur von .NET Frame- work 4.8 und .NET Core 3.0 eingliedert und welche Stärken und Eigenschaften die WPF hat, lesen Sie in Abschnitt 1.1. In Abschnitt 1.2 erfahren Sie in einem Schnelldurchlauf der letzten Jahrzehnte, wie sich die Programmierung unter Windows entwickelt hat. Wir beginnen bei Windows 1.0 und enden bei der WPF und Windows 10. Die WPF nutzt zum Zeichnen DirectX. Wie die dafür benötigte Architektur aussieht und funktioniert, lesen Sie in Abschnitt 1.3. Sie lernen dabei auch die zentralen Assemblies der WPF kennen, die Sie später auch in all Ihren WPF-Projekten wiederfinden. In Abschnitt 1.4, dem letzten Abschnitt dieses Kapitels, finden Sie einen Überblick über die zentralen Konzepte der WPF. Dazu gehört die XML-basierte Beschreibungssprache XAML, mit der Sie in der WPF Ihre Benutzeroberflächen deklarieren. Ebenfalls lernen Sie in diesem Abschnitt die Konzepte wie Dependency Properties, Routed Events oder Styles und Templa- tes näher kennen. Diese Konzepte tauchen in den folgenden Kapiteln immer wieder auf.
1.1 Die WPF und .NET
Mit der Windows Presentation Foundation (WPF) steht seit der Einführung des .NET Frame- works 3.0 im Jahr 2006 ein mächtiges Programmiermodell zum Entwickeln von Benutzer- oberflächen zur Verfügung.
1.1.1 .NET Core 3.0 und .NET Framework 4.8 Die WPF wurde mit dem .NET Framework 3.0 eingeführt. Mit dem aktuellen .NET Framework 4.8 hat Microsoft angekündigt, dass dies die letzte Hauptversion des .NET Frameworks sein wird. Zukünftige Entwicklungen und Innovationen finden auf .NET Core statt.
43 7201.book Seite 44 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 45 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.1 Die WPF und .NET
.NET Core ist Microsofts moderne Cross-Platform-Implementierung von .NET, die auf Linux, .NET Core ist die Zukunft von .NET. Microsoft wird das .NET Framework in Zukunft weiter un- 1 macOs und Windows läuft. Mit .NET Core 3.0 werden auch mit der WPF entwickelte Desktop- terstützen, aber die Innovation findet in .NET Core statt. Falls Sie bestehende WPF-Anwen- Anwendungen unterstützt. Doch Moment, heißt das, dass Ihre WPF-Anwendung auch unter dungen mit dem .NET Framework entwickelt haben und Sie keine großen Änderungen pla- Linux und macOS läuft? nen, können Sie diese auf .NET Framework lassen. Falls Sie jedoch weitere Features planen, Nein, dies ist nicht der Fall. Abbildung 1.1 zeigt die Übersicht von .NET Core 3.0. Es gibt dort empfiehlt sich eine Migration von .NET Framework zu .NET Core. Der Code bleibt dabei einen Teil, der cross-platform läuft. Zu diesem Teil gehören ASP.NET Core zum Entwickeln gleich. Lediglich die Projektdateien (.csproj) müssen angepasst werden. Am einfachsten kön- von Web-Anwendungen, Entity Framework und Entity Framework Core zum Zugriff auf nen Sie den Unterschied der Projektdateien sehen, indem Sie neue WPF-Projekte in Visual Studio 2019 sowohl mit .NET Framework als auch mit .NET Core erstellen und dann die Pro- Daten und ML.NET zum Nutzen von Machine-Learning-Methoden in .NET-Applikationen. jektdateien entsprechend vergleichen. Die WPF und Windows Forms (WinForms) werden als zusätzliche Bibliotheken unterstützt, die nur unter Windows verfügbar sind. Der Grund dafür ist, dass die WPF und WinForms In diesem Buch wird .NET Core 3.0 zum Entwickeln der WPF-Anwendungen verwendet. Den viele Abhängigkeiten zu Windows haben. Somit lässt sich die WPF nur nutzen, um Desktop- Code, den Sie dabei lernen, können Sie natürlich auch in einer auf .NET Framework basieren- Applikationen für Windows zu entwickeln. Desktop-Applikationen für Linux und macOs las- den WPF-Anwendung nutzen. Die Konzepte sind dieselben, nur der genutzte Unterbau ist sen sich mit der WPF und .NET Core 3.0 nicht entwickeln. ein anderer.
.NET Core 3.0 1.1.2 Die WPF und Visual Studio 2019 Für die WPF bietet Visual Studio 2019 verschiedene Projektvorlagen und einen intelligenten Windows Cross-platform Oberflächen-Designer. Neben Visual Studio 2019 gibt es weitere Werkzeuge, die Sie beim Ent- wickeln Ihrer Anwendungen unterstützen. Besonders zu erwähnen ist das Design-Tool Web Daten AI Blend, das zusammen mit Visual Studio 2019 auf Ihrem Rechner installiert wird. Sie können WPF Blend zum Erstellen reichhaltiger Benutzeroberflächen mit der WPF einsetzen. Blend legt Entity dabei ein spezielles Augenmerk auf das Design der Anwendung. ASP.NET Framework WinForms ML.NET Core (Core) Natürlich verwenden Sie zum Programmieren von WPF-Anwendungen nach wie vor Visual Studio. Die zusätzlichen Programme wie Blend bieten Ihnen allerdings beim Benutzerober- flächen-Design etwas mehr Unterstützung als Visual Studio. Sie finden in Blend ähnliche Funktionen und Werkzeuge wie in einem Grafikprogramm, beispielsweise Farbpaletten, Timelines für Animationen, Pens, Pencils und vieles mehr. Damit kann ein Grafikdesigner Abbildung 1.1 .NET Core 3.0 und WPF arbeiten, ohne den vom Programm generierten Code zwingend kennen und verstehen zu müssen. Jetzt stellt sich die Frage, welches Framework Sie zum Entwickeln Ihrer WPF-Anwendung ein- setzen sollten: .NET Framework 4.8 oder .NET Core 3.0? Visual Studio 2019 bietet Ihnen Pro- jektvorlagen für beide Plattformen. Doch die Empfehlung ist klar. 1.1.3 Die WPF als zukünftiges Programmiermodell Wenn Sie eine neue WPF-Applikation entwickeln, sollten Sie definitiv .NET Core 3.0 wählen. Bei manchen Programmierern, die die technische Entwicklung im Hause Microsoft nicht .NET Core 3.0 bietet Ihnen im Gegensatz zum .NET Framework 4.8 verschiedene Vorteile. Bei- mitverfolgt haben, sorgte die Nachricht von einem weiteren Programmiermodell für Benut- spielsweise lässt sich Ihre WPF-Applikation gebündelt zusammen .NET Core ausliefern, wo- zeroberflächen als Teil des .NET Frameworks 3.0 zuerst für etwas Verwirrung. Schließlich durch auf dem Zielrechner kein .NET installiert sein muss. Ebenso werden viele der neueren enthielt das .NET Framework seit Version 1.0 mit Windows Forms ein bewährtes Program- C#-Features ab C# 8.0 nur unter .NET Core 3.0 unterstützt, nicht unter .NET Framework 4.8. miermodell zur Entwicklung von Desktop-Anwendungen. Insbesondere im .NET Framework Der Grund ist, dass einige Sprach-Features Erweiterungen an der Common Language Run- 2.0 wurde Windows Forms stark verbessert und erfreute sich großer Beliebtheit. Viele Ent- time (CLR) voraussetzen, und diese Erweiterungen würden im .NET Framework zu einigen wickler stellten sich demzufolge die Frage, was das neue Programmiermodell für Vorteile Kompatibilitätsproblemen führen. Die Erweiterungen sind somit nur in .NET Core verfüg- bringen würde und warum sie in Zukunft die WPF anstelle von Windows Forms einsetzen bar. sollten.
44 45 7201.book Seite 46 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 47 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.1 Die WPF und .NET
Wer damals bereits erste Gehversuche mit den von Microsoft als Download bereitgestellten 1 Vorabversionen des .NET Frameworks 3.0 – den sogenannten Community Technology Pre- views (CTPs) – hinter sich hatte, der wusste, dass mit der WPF auch scheinbar komplexe Auf- gaben (wie die Programmierung von animierten, rotierenden 3D-Objekten mit Videos auf der Oberfläche) relativ einfach und schnell umsetzbar sind (siehe Abbildung 1.2, welche aus Kapitel 14, »3D-Grafik«, stammt).
Abbildung 1.2 Ein 3D-Würfel, auf dem ein Video abläuft Abbildung 1.3 Die Anwendung »FriendStorage« speichert Listen mit Freunden. Sie verwendet ver- schiedene Features der WPF wie Commands, Styles, Trigger, Animationen und Data Binding. Allerdings trat beim Versuch, eine etwas umfangreichere Anwendung mit der WPF zu ent- wickeln, meist die erste Ernüchterung auf. Die Einstiegshürde ist bei der WPF relativ mäch- Bisher konnten grafisch hochwertige Anwendungen nur mit weiteren einarbeitungsintensi- tig, das heißt, sie ist um einiges höher als jene bei Windows Forms. Die ersten Erfolgserleb- ven Technologien wie DirectX erstellt werden. Mit der WPF stellt Microsoft im Zeitalter von nisse mit der WPF werden Sie zwar schon bald haben, für die professionelle und erfolgreiche Windows 10 ein einheitliches, zeitgemäßes Programmiermodell zur Verfügung, das zur Ent- Entwicklung müssen Sie jedoch auch die Konzepte und Hintergründe der WPF verstanden wicklung moderner Desktop-Anwendungen keine Kenntnisse über komplexe, weitere Tech- haben. Dazu gehören unter anderem Layout, Dependency Properties, Routed Events sowie nologien wie eben DirectX erfordert. Und das Besondere an dem einheitlichen Program- Styles und Templates. Haben Sie diesen Punkt erreicht, können Sie mit der WPF auch sehr miermodell der WPF ist, dass Sie für die Verwendung von Animationen, Data Bindings oder komplexe Anwendungen erstellen, ohne auf komplizierte weitere Technologien zugreifen Styles immer die gleichen Konstrukte verwenden, egal ob Sie damit 2D-, 3D-, Text- oder sons- zu müssen. tige Inhalte beeinflussen wollen. Haben Sie also einmal gelernt, wie Sie ein 2D-Element ani- In diesem Buch werde ich, um die Konzepte zu erläutern, auch einige Beispiele aus der An- mieren, können Sie das Erlernte auch auf 3D-Objekte anwenden. wendung FriendStorage herauspicken. FriendStorage ist eine kleine Anwendung, die Sie beim Studieren der WPF-Konzepte unterstützt. In FriendStorage können Sie eine Liste mit Freunden speichern und für jeden Freund verschiedene persönliche Daten und ein Bild er- 1.1.4 Stärken und Eigenschaften der WPF fassen (siehe Abbildung 1.3). Die Anwendung zeigt auf der rechten Seite eine Liste Ihrer Mit 2D, 3D und Text beziehungsweise Dokumenten wurden schon einige der Stärken der Freunde an. Auf der linken Seite sehen Sie die Details zum aktuell in der Liste ausgewählten WPF angeschnitten. Im Gegensatz zu Windows Forms bietet die WPF viele weitere, vorteil- Freund. hafte Eigenschaften, die sich nicht nur auf die Erstellung reichhaltiger Benutzeroberflächen aus Sicht des Grafikers beziehen. Unter anderem sind dies erweitertes Data Binding, verbes-
46 47 7201.book Seite 48 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 49 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.1 Die WPF und .NET
serte Layoutmöglichkeiten, ein flexibles Inhaltsmodell, eine verbesserte Unterstützung für Eigenschaft Beschreibung 1 Audio/Video, integrierte Animationen, Styles, Templates und vieles mehr. In Tabelle 1.1 fin- den Sie eine Handvoll der wohl bedeutendsten Eigenschaften der WPF. »lookless« Aufgrund dieser Flexibilität und der Tatsache, dass die meisten Controls der Controls WPF als Custom Control implementiert sind, müssen Sie keine Subklassen Eigenschaft Beschreibung (Forts.) mehr erstellen, um lediglich das Aussehen anzupassen. Es sind folglich weniger eigene Custom Controls als in bisherigen Programmiermodellen Flexibles Die WPF besitzt ein flexibles Inhaltsmodell. In bisherigen Programmiermo- notwendig. Inhaltsmodell dellen, wie Windows Forms, konnte beispielsweise ein Button lediglich Text oder ein Bild als Inhalt enthalten. Mit dem flexiblen Inhaltsmodell der WPF Daten Die Elemente in Ihrer Applikation können Sie mit Data Binding an verschie- kann ein Button – genau wie viele andere visuelle Elemente – einen beliebi- dene Datenquellen binden. Dadurch ersparen Sie sich die Programmierung gen Inhalt haben. So ist es beispielsweise möglich, in einen Button ein Lay- von Event Handlern, die die Benutzeroberfläche oder die Datenquelle bei out-Panel zu setzen und darin wiederum mehrere 3D-Objekte und Videos einer Änderung aktualisieren. Außer durch Data Binding können Sie mit unterzubringen. Ihrer Kreativität sind keine Grenzen gesetzt. Data Templates das Aussehen Ihrer Daten auf der Benutzeroberfläche defi- nieren. Layout Die WPF stellt einige Layout-Panels zur Verfügung, um Controls in einer Anwendung dynamisch anzuordnen und zu positionieren. Aufgrund des fle- 2D- und 3D-Grafiken können Sie in der WPF auf dieselbe Weise zeichnen und animie- xiblen Inhaltsmodells lassen sich die Layout-Panels der WPF auch beliebig 3D-Grafiken ren wie 2D-Grafiken. Dazu stellt die WPF viele Zeichenwerkzeuge bereit, wie ineinander verschachteln, wodurch Sie in Ihrer Anwendung auch ein sehr beispielsweise die verschiedenen Brushes. Auch eine Benutzerinteraktion komplexes Layout erstellen können. mit 3D-Elementen ist möglich.
Styles Ein Style ist eine Sammlung von Eigenschaftswerten. Diese Sammlung lässt Animationen Die WPF besitzt einen integrierten Mechanismus für Animationen. Wäh- sich einem oder mehreren Elementen der Benutzeroberfläche zuweisen, rend Sie bisher für Animationen einen Timer und einen dazugehörigen wodurch deren Eigenschaften dann die im Style definierten Werte an- Event Handler verwendet haben, ist dies jetzt wesentlich einfacher reali- nehmen. Sie definieren einen Style üblicherweise als Ressource, um ihn siert, wie Sie in Kapitel 15, »Animationen«, sehen werden. beispielsweise mehreren Buttons zuzuweisen, die alle die gleiche Hinter- Audio/Video Audio- und Video-Elemente lassen sich einfach in Ihre Applikation einbin- grundfarbe und die gleiche Breite haben sollen. Ohne Styles müssten Sie auf den. Dafür stehen verschiedene Klassen zur Verfügung. jedem Button diese Properties setzen. Mit Styles setzen Sie lediglich die Style-Property auf den Buttons, was sogar implizit passieren kann; mehr Text & Die WPF stellt eine umfangreiche API zum Umgang mit Text und Dokumen- dazu folgt in Kapitel 11, »Styles, Trigger und Templates«. Dokumente ten bereit. Es werden fixe und fließende Dokumente unterstützt. Fixe Doku- mente unterstützen eine gleichbleibende, fixierte Darstellung des Inhalts – Trigger Trigger erlauben es Ihnen, auf deklarativem Weg festzulegen, wie ein Con- ähnlich wie PDF-Dokumente –, während fließende Dokumente ihren Inhalt trol auf bestimmte Eigenschaftsänderungen oder Events reagieren soll. Mit an verschiedene Faktoren anpassen, wie beispielsweise an die Größe des Triggern können Sie bereits deklarativ Dinge erreichen, für die Sie ansonsten Fensters. Zum Anzeigen der Dokumente stehen verschiedene Controls zur einen Event Handler benötigen würden. Trigger definieren Sie meist in Verfügung. einem Style oder einem Template.
»lookless« Custom Controls sind bei der WPF »lookless«, das heißt, Sie trennen ihre Tabelle 1.1 Wichtige Eigenschaften der WPF (Forts.) Controls visuelle Erscheinung von ihrer eigentlichen Logik und ihrem Verhalten. Das Aussehen eines Controls wird dabei mit einem ControlTemplate beschrie- Neben all den in Tabelle 1.1 dargestellten Eigenschaften, die Sie in einzelnen Kapiteln dieses ben. Das Control selbst definiert kein Aussehen, sondern nur Logik und Ver- Buches wiederfinden, ist eine weitere große Stärke der WPF die verbesserte Unterstützung halten – daher »lookless«. Durch Ersetzen des ControlTemplates (durch des Entwicklungsprozesses zwischen dem Designer einer Benutzeroberfläche und dem Ent- Setzen der Template-Property der Klasse Control) lässt sich das komplette wickler, der die eigentliche Geschäftslogik implementiert. Dies wird durch die XML-basierte Aussehen eines Controls anpassen. Beschreibungssprache Extensible Application Markup Language (XAML, sprich »Semmel«) erreicht, die mit der WPF eingeführt wurde. XAML wird in der WPF zur deklarativen Beschrei- Tabelle 1.1 Wichtige Eigenschaften der WPF
48 49 7201.book Seite 50 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 51 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.2 Von Windows 1.0 zur Windows Presentation Foundation
bung von Benutzeroberflächen eingesetzt. Sie können Ihre Benutzeroberflächen zwar auch passt und erweitert. Sie tragen seitdem die Namen gdi32.dll, kernel32.dll und user32.dll. Man 1 weiterhin in C# erstellen, profitieren dann aber nicht von den Vorteilen, die Ihnen XAML spricht in diesem Zusammenhang statt von der »Windows-API« auch von der »Win32-API«. bietet. So dient XAML beispielsweise im Entwicklungsprozess als Austauschformat zwischen Designer und Entwickler. Es gibt mittlerweile zig Programme, die XAML-Dateien öffnen kön- 1.2.1 Die ersten Wrapper um die Windows-API nen und zum Editieren einen grafischen Editor bereitstellen, wodurch ein Designer Ihre Be- nutzeroberfläche wie eine Grafik »designen« kann. Sie werden XAML in den Kapiteln dieses Da bei der direkten Verwendung der Windows-API viele Funktionsaufrufe auf sehr niedri- Buchs mit allen Tricks und Kniffen kennenlernen. Insbesondere in Kapitel 3, »XAML«, dreht gem, detailliertem Betriebssystem-Level notwendig waren, was zu Unmengen von Code sich alles um diese Markup-Sprache. führte, fiel bei der zeitintensiven Programmierung der Blick auf das Wesentliche sehr schwer, weil man so viele Details programmieren musste. Es war nur eine Frage der Zeit, bis die ersten Programmbibliotheken entstanden, die die Aufrufe der Windows-API kapselten 1.1.5 Auf Wiedersehen, GDI+ und diese Aufrufe zu logischen, abstrakteren Einheiten zusammenfassten. Außer durch ihr Modell, das vorsieht, Benutzeroberflächen mit XAML zu erstellen, unter- Für C++ entwickelte Microsoft die Microsoft Foundation Classes (MFC) als objektorientierte scheidet sich die WPF auch aus rein technologischer Sicht von Windows Forms und den bis- »Wrapper«-Bibliothek um die Windows-API. Borland brachte mit der Object Window Library herigen Programmiermodellen unter Windows. Erstmals baut die grafische Darstellung (OWL) ein Konkurrenzprodukt auf den Markt. Auch im Zeitalter von .NET werden von nicht auf der GDI-Komponente (Graphics Device Interface) der Windows-API auf, wie das bei Windows Forms die Funktionen der Windows-API gekapselt. Man könnte also sagen, dass die Windows Forms und vorherigen Programmiermodellen der Fall war (Windows Forms ver- Programmierung von Windows-Applikationen seit der Einführung von Windows 1.0 im Jahr wendet GDI+, eine verbesserte Variante von GDI). Stattdessen greift die WPF zur Darstellung 1985 in den Grundzügen gleich geblieben ist – im Hintergrund wurde seit eh und je auf die des Fensterinhalts auf DirectX zurück. Programmbibliotheken der Windows-API zugegriffen. Ja, Sie haben richtig gelesen. Für das Zeichnen der Pixel (Rendering) macht die WPF von dem bisher meist nur in Spielen verwendeten DirectX Gebrauch. DirectX ist eine aus mehreren 1.2.2 Windows Forms und GDI+ APIs bestehende Suite, die auf Windows-Rechnern die Kommunikation zwischen Hardware und Software ermöglicht. Dadurch lassen sich die Möglichkeiten der in heutigen Computern Die Aufrufe der zur Windows-API gehörenden Programmbibliothek GDI+ kapselt Windows mittlerweile standardmäßig eingebauten Grafikkarten mit 3D-Beschleunigern richtig aus- Forms hauptsächlich in der Klasse System.Drawing.Graphics. Jedes Control in Windows nutzen. Bisher, so auch unter Windows Forms, blieben die meisten Möglichkeiten der vor- Forms nutzt ein Graphics-Objekt zum Zugriff auf GDI+. In Abbildung 1.4 ist zu sehen, dass handenen Hardware völlig ungenutzt. GDI+ die entsprechenden Befehle an die Grafikkarte weitergibt, um das Control auf den Bild- schirm zu zeichnen. (Das Zeichnen auf den Bildschirm nennt man Rendering.) Den guten alten Grafikschnittstellen GDI und GDI+ kehrt die WPF also den Rücken zu. Ver- ständlich, denn DirectX ist natürlich weitaus attraktiver und leistungsfähiger. Zu Ehren der Ein einzelnes Control von Windows Forms und Win32 wird aus Windows-Sicht als ein Fens- klassischen Windows-API und der darin enthaltenen GDI-Komponente wagen wir einen ter betrachtet. Jedes Fenster wird über einen Window-Handle (HWND-Datentyp in C/C++, Sys- ganz kurzen Rückblick ins Jahr 1985, als alles begann. tem.IntPtr in .NET) referenziert und besitzt einen bestimmten Bereich auf dem Bildschirm, auf den es zeichnen darf. Auf die Bereiche eines anderen Window-Handles darf das Fenster nicht zeichnen. 1.2 Von Windows 1.0 zur Windows Presentation Foundation Die WPF schlägt einen neuen, zeitgemäßen Weg ein und lässt die »Altlasten« vergangener Jahrzehnte hinter sich. Ein Control hat bei der WPF keinen Window-Handle mehr;1 es kann Als im November 1985 die erste Version von Windows auf den Markt kam – eine grafische Er- somit auch auf die Pixel anderer Controls zeichnen, wodurch beispielsweise Transparenz- weiterung zum damaligen Betriebssystem MS-DOS –, gab es nur eine Möglichkeit, Windows- effekte möglich sind. Anwendungen zu schreiben: Mit der Programmiersprache C wurde auf die Funktionen der ebenfalls in C geschriebenen Windows-Programmierschnittstelle – kurz Windows-API – zu- gegriffen, um Fenster zu erstellen und um weitere Systemfunktionalität zu verwenden. Mit der Umstellung auf eine 32-Bit-Architektur wurden die Bibliotheken der Windows-API ange- 1 Es gibt einige Ausnahmen, wie beispielsweise ein Window, das in einen Top-Level-Handle gesetzt wird. Auch ein Kontextmenü wird bei der WPF in einen Window-Handle gesetzt, damit es immer im Vorder- grund ist.
50 51 7201.book Seite 52 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 53 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.3 Die Architektur der WPF
Mit dem .NET Framework 4.0 erhielt die WPF ein DataGrid, und es gab bereits genügend Con- 1 Windows Forms trols aus der dritten Reihe von altbekannten Herstellern wie beispielsweise Infragistics, Dev- Express oder Telerik. Mit dem aktuellen .NET Framework 4.8 und .NET Core 3.0 wurde insbe- sondere der WPF-Designer in Visual Studio 2019 verbessert. Auch das Schreiben von XAML- GDI+ Grafikkarte Code ist jetzt noch einfacher, da die IntelliSense-Unterstützung deutlich besser ist. Mit Visual Studio 2019 wird auch das Design-Tool Blend installiert. Windows/Controls Hinweis .NET + Native Im Gegensatz zu Visual Studio erlaubt Blend das Definieren von Animationen über eine rein grafische Benutzeroberfläche, die keinerlei XAML-Kenntnisse voraussetzt. Es gibt in Blend ein Abbildung 1.4 In Windows Forms werden Controls mit GDI+ gezeichnet. Timeline-Fenster ähnlich wie das aus Adobe Flash, in dem sich eine Animation über einen Zeitraum mit einfachen Mausklicks definieren lässt. 1.2.3 Die Windows Presentation Foundation Neben der grafischen Unterstützung von Animationen besitzt Blend viele designerfreund- liche Merkmale, wie Farbpaletten, eine Werkzeugleiste mit aus Grafikprogrammen bekann- Mit der Entwicklung der WPF begann Microsoft bereits, bevor im Jahr 2001 die erste Version ten Werkzeugen wie Stift, Pinsel, Radiergummi etc. des .NET Frameworks erschien. Damals war den Entwicklern und Entscheidern bei Microsoft bereits klar, dass .NET die Zukunft sein würde. Somit entschieden sie sich, auch die WPF in Blend wird allerdings auch lediglich als Programm für den Feinschliff der Benutzeroberfläche Managed Code statt in nativem Code zu implementieren. betrachtet und wird Visual Studio somit keinesfalls ersetzen. In diesem Buch wird mit der WPF und XAML programmiert und folglich außer Visual Studio kein anderes Programm ge- Während die bisherigen Programmiermodelle von Microsoft für Benutzeroberflächen meist nutzt. Wenn Sie später Blend verwenden, werden Sie nach der Lektüre dieses Buchs den von nur dünne Wrapper um die Windows-API darstellten (wie eben auch Windows Forms), ist die Blend und auch von anderen Programmen generierten XAML-Code verstehen. WPF das erste, umfangreiche Programmiermodell für Benutzeroberflächen, das fast voll- ständig in .NET geschrieben ist. Die damaligen Gründe für Windows Forms – mehr Controls und bessere Designunterstüt- Eines der Designziele der WPF war es, nicht auf den vielen in die Jahre gekommenen Funktio- zung in Visual Studio 2005 – sind aus meiner Sicht heute nicht mehr gegeben. Auch für typi- nen der Windows-API aufzubauen. So setzt die WPF beispielsweise für die Darstellung sche datenintensive Geschäftsanwendungen ist die WPF bestens geeignet, da sie mit Fea- DirectX anstelle von GDI+ ein, um die Leistung der heutigen Grafikkarten nicht nur in Spie- tures wie dem umfangreichen Data Binding optimale Unterstützung bietet. len, sondern auch in »gewöhnlichen« Windows-Anwendungen voll und ganz auszureizen. Haben Sie sich für die WPF entschieden, stehen Ihnen für Ihre bereits entwickelten Win32- Dabei werden die Komponenten einer WPF-Anwendung nicht mehr durch das Betriebssys- und Windows-Forms-Anwendungen verschiedene Interoperabilitätsmöglichkeiten mit der tem, sondern durch die WPF selbst unter Verwendung von DirectX gezeichnet. Ein einzelnes WPF zur Verfügung. In Visual Studio gibt es zwar keinen integrierten Migrationsmechanis- Control der WPF besitzt nicht wie ein Window-Handle unter Win32 seinen Bereich, in dem es mus von Windows Forms/Win32 zur WPF – die Programmiermodelle sind einfach zu unter- zeichnen darf. Somit kann ein Control der WPF wie gesagt über die Pixel eines anderen Con- schiedlich –, doch die in .NET enthaltenen Klassen für Interoperabilität zwischen WPF und trols zeichnen, was Transparenzeffekte ermöglicht. Windows Forms/Win32 bieten Ihnen verschiedene Möglichkeiten, Ihre älteren Anwendun- Durch die Tatsache, dass die WPF alles selbst zeichnet, sind das flexible Inhaltsmodell oder gen nach und nach zu migrieren. In Kapitel 20, »Interoperabilität«, erfahren Sie mehr über Dinge wie Templates – mit denen Sie das Erscheinungsbild von Controls individuell an Ihre verschiedene Interoperabilitätsszenarien und mögliche Migrationsstrategien. Bedürfnisse anpassen können – überhaupt erst möglich. Nach der Einführung des .NET Frameworks 3.0 war es noch so, dass Windows Forms mit Con- trols wie der DataGridView Komponenten besaß, die man in der WPF vergeblich suchte. Auch 1.3 Die Architektur der WPF der Windows-Forms-Designer in Visual Studio 2005 war dem damals zur Verfügung stehen- Nachdem Sie jetzt bereits einige Eigenschaften und Hintergründe der WPF kennen, ist es an den WPF-Designer weit voraus. Somit lautete der Grundsatz zu dieser Zeit, Anwendungen, der Zeit, einen Blick auf die Architektur der WPF zu werfen. Der Kern der WPF besteht aus drei die ohne verschiedene Medienelemente und ohne grafische Kunststücke auskamen, weiter- Bibliotheken: hin mit Windows Forms zu entwickeln.
52 53 7201.book Seite 54 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 55 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.3 Die Architektur der WPF
̈ MilCore.dll Beim Entwickeln einer WPF-Anwendung werden Sie mit MilCore nicht direkt in Kontakt 1 ̈ PresentationCore.dll kommen. Die Programmierschnittstelle, die zur Programmierung von WPF-Anwendungen genutzt wird, liegt komplett in Managed Code vor. Die Assemblies PresentationCore.dll und ̈ PresentationFramework.dll PresentationFramework.dll bilden dabei die zentralen Bausteine der WPF. Aufgrund ihrer Obwohl Microsoft sich entschieden hat, die WPF in .NET statt in nativem Code zu implemen- Implementierung in Managed Code sind sie in Abbildung 1.5 oberhalb der Laufzeitumge- tieren, setzt die WPF aus Performance-Gründen auf einer in nativem Code geschriebenen bung von .NET – der Common Language Runtime (CLR) – positioniert. PresentationCore und Schicht namens Media Integration Layer (MIL) auf. Die Kernkomponente des Media Integra- PresentationFramework enthalten Logik für Controls, Layout, Dokumente oder Data Bind- tion Layers ist die MilCore.dll. ing. Darüber hinaus kapselt PresentationCore die Aufrufe der nativen MilCore-Komponente. Wie Abbildung 1.5 zeigt, ist MilCore unter anderem für die Darstellung von 2D- und 3D-Inhal- Beide Komponenten bauen auf der Assembly WindowsBase.dll auf, die nicht Teil der WPF ist, ten, Bildern, Videos, Text und Animationen verantwortlich. Zur Darstellung der Informatio- sondern Klassen für alle mit dem .NET Framework 3.0 neu eingeführten Programmiermo- nen auf dem Bildschirm greift MilCore auf die Funktionalität von DirectX zu, um die Leis- delle enthält. So finden Sie in WindowsBase beispielsweise Klassen für das erweiterte Eigen- tung der Grafikhardware voll auszunutzen. schaftssystem mit Dependency Properties, das bei der WPF und auch bei der Windows Workflow Foundation (WF) verwendet wird. Sehen wir uns genauer an, was die drei Komponenten der WPF (MilCore, PresentationCore PresentationFramework Controls Dokumente und PresentationFramework) und auch die WindowsBase-Komponente enthalten, was ihre Aufgaben sind und – was wohl am spannendsten ist – wie sie diese Aufgaben meistern. Layout Data Binding ... PresentationCore
1.3.1 MilCore – die »Display Engine« ... WindowsBase Eigenschaftssystem Die in nativem Code geschriebene Komponente MilCore.dll kapselt DirectX. MilCore ist in der WPF für die Darstellung von 3D, 2D, Text, Video, Bildern, Effekten und Animationen zu- ständig. Prinzipiell alles, was in einer WPF-Anwendung gezeichnet wird, basiert auf der Funk- Common Language Runtime (CLR) tionalität von MilCore und DirectX. Ein wohl entscheidender Vorteil, den Ihre WPF-Anwendung durch MilCore erreicht, ist die Verantwortlich für Darstellung von: vektorbasierte Darstellung. MilCore stellt alle Inhalte vektorbasiert dar; dadurch können Sie Ihre Anwendungen beliebig skalieren, ohne dass diese an »Schärfe« verlieren. 2D Bilder Video ... MilCore Im Folgenden werfen wir einen Blick darauf, wie MilCore die Aufgabe wahrnimmt, die einzel- 3D Effekte Animationen nen Elemente Ihrer Anwendung auf dem Bildschirm darzustellen. Den darzustellenden Bildschirminhalt verwaltet MilCore in Form einer Baumstruktur, als sogenannten Composition Tree (siehe Abbildung 1.6). Dieser Baum besteht aus einzelnen User32 DirectX Knoten (Composition Nodes), die Metadaten und Zeichnungsinformationen enthalten. Bei Änderungen am Composition Tree generiert MilCore die entsprechenden DirectX-Befehle, die die Änderungen visuell umsetzen und mithilfe der Grafikkarte auf dem Bildschirm dar- Kernel stellen. Die vielen Composition Nodes werden also durch MilCore zu einem großen, zu zeich- nenden Bild zusammengesetzt; dieser Prozess wird auch als Composition bezeichnet. Das
Abbildung 1.5 Die WPF-Architektur mit den Hauptkomponenten »PresentationFramework«, zusammengesetzte Bild wird dann auf dem Bildschirm dargestellt. »PresentationCore« und »MilCore« In früheren Modellen, wie Windows Forms, hatte jedes Control seinen eigenen Ausschnitt, in dem es sich selbst zeichnen durfte. Der Ausschnitt war über ein Window-Handle (HWND) de- finiert. Über den Ausschnitt kam das Control nicht hinaus. Dieses System wird als Clipping-
54 55 7201.book Seite 56 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 57 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.3 Die Architektur der WPF
System bezeichnet, da in ihm einfach am Rand abgeschnitten beziehungsweise geclippt wird 1 und jedes Control seinen eigenen Ausschnitt hat, auf dem es sich zeichnen darf. Bei einem Hinweis Composition-System hingegen wird nicht abgeschnitten. Stattdessen darf jedes Control Tatsächlich verwendet die WPF im Hintergrund einen weiteren Thread, der für das Rendering überall zeichnen, und am Ende wird alles zu einem großen Bild zusammengefügt. Mit der (also das Zeichnen auf den Bildschirm) verantwortlich ist. Eine WPF-Anwendung besitzt Composition in MilCore kann ein Control auch über die Pixel eines anderen Controls zeich- somit immer zwei Threads: nen, wodurch Effekte wie Halbtransparenz erst möglich werden. ̈ einen UI-Thread, der Benutzereingaben mit der Maus oder Tastatur entgegennimmt, Der Composition Tree ist mit allen Zeichnungsinformationen zwischengespeichert. Da- Events entgegennimmt und Ihren Code ausführt durch kann die Benutzeroberfläche sehr effektiv und schnell neu gezeichnet werden, auch ̈ einen Render-Thread, der für das Zeichnen der Inhalte verantwortlich ist dann, wenn Ihre Anwendung gerade beschäftigt ist. Die Zeiten von visuell eingefrorenen An- wendungen sind also vorbei. Wie bereits erwähnt, werden Sie die Programmbibliothek MilCore.dll nicht direkt verwen- Der zur Laufzeit mit den Zeichnungsinformationen bestückte und in der nativen MilCore- den, sondern über .NET-Assemblies indirekt auf sie zugreifen. MilCore wird Ihnen daher Komponente lebende Composition Tree besitzt auf der .NET-Seite ein Pendant, den soge- nicht begegnen, zumal die Bibliothek nicht öffentlich ist. Somit stellen die drei .NET-Assem- nannten Visual Tree. Der Visual Tree setzt sich aus allen visuellen Elementen einer WPF- blies den Teil dar, mit dem Sie bei der Entwicklung von WPF-Anwendungen in Berührung Anwendung zusammen. Das Prinzip der Entwicklung von WPF-Anwendungen und -Controls kommen. Im Folgenden sehen wir uns diese drei Assemblies kurz an. besteht im Grunde darin, mit XAML und/oder prozeduralem Code eine Hierarchie von visu- ellen Elementen zu erzeugen, wie etwa Window, TextBox und Button. Die einzelnen Controls in 1.3.2 WindowsBase dieser Hierarchie setzen sich wiederum aus einfacheren visuellen Elementen zusammen, Die Assembly WindowsBase.dll enthält die Basislogik für Windows-Anwendungen und ist in wie Rectangle, TextBlock oder Border. Alle visuellen Elemente haben die gemeinsame Basis- .NET geschrieben. Unter anderem ist in der Assembly WindowsBase die Logik für das erwei- klasse Visual. Die gesamte Hierarchie, einschließlich der einfacheren visuellen Elemente, terte Eigenschaftssystem implementiert, das aus den sogenannten Dependency Properties wird daher als Visual Tree bezeichnet. besteht. Dependency Properties werden in Kapitel 7, »Dependency Properties«, genauer be- Über einen zweiseitigen Kommunikationskanal sind der Visual Tree und der Composition trachtet. Weiter enthält WindowsBase Low-Level-Klassen, die notwendig sind, um beispiels- Tree miteinander verbunden, wie in Abbildung 1.6 zu sehen ist. Über diesen Kommunika- weise in Ihrer WPF-Anwendung die Nachrichtenschleife zu starten. Die Assemblies Presenta- tionskanal werden Änderungen auf die jeweils andere Seite übertragen. Dabei sind die bei- tionCore und PresentationFramework bauen beide auf WindowsBase auf. den Bäume nicht zu 100 % identisch; zum Beispiel können einem Knoten im Visual Tree mehrere Knoten im Composition Tree entsprechen. Objekte mit hohem Speicherplatz- bedarf, wie etwa Bitmaps, werden gemeinschaftlich verwendet. Wie Abbildung 1.6 zeigt, ver- 1.3.3 PresentationCore wendet MilCore DirectX, das die entsprechenden Befehle an die Grafikkarte gibt, wodurch In PresentationCore ist auf der .NET-Seite die Verbindung der beiden Baumstrukturen Visual die Darstellung auf dem Bildschirm (also das Rendering) erfolgt. Tree und Composition Tree (auf MilCore-Seite) in der abstrakten Klasse System.Windows. Media.Visual implementiert. Der Visual Tree einer WPF-Anwendung besteht aus Objekten von Subklassen der Klasse Visual. Die Klasse Visual enthält private Methoden zur Kommu- PresentationCore MilCore nikation mit dem auf MilCore-Seite bestehenden Composition Tree. Visual dient als Basis- klasse für jene Klassen, die in der WPF visuell dargestellt werden sollen.
DirectX Grafikkarte Neben Visual enthält PresentationCore einige weitere interessante Klassen, unter anderem die Klasse UIElement, die in der WPF von Visual ableitet und eine konkrete Implementierung Visual Tree Composition Tree für visuelle Elemente darstellt. Mehr zu Visual, UIElement und weiteren Klassen möchte ich Ihnen an dieser Stelle noch nicht verraten; ich werde sie in Kapitel 2, »Das Programmier- .NET Native modell«, und in den folgenden Kapiteln ausführlicher behandeln.
Abbildung 1.6 Die Kommunikation zwischen der .NET-Komponente »PresentationCore« und der auf DirectX aufbauenden Komponente »MilCore«
56 57 7201.book Seite 58 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 59 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
und der entsprechende DirectX-Befehl zur Neuzeichnung der Border-Linie erstellt. In 1.3.4 PresentationFramework 1 Windows Forms wäre ein Neuzeichnen des ganzen Buttons notwendig. Die wichtigsten Klassen der WPF für die Entwicklung der grafischen Benutzerschnittstelle wie auch der Funktionalität einer Anwendung befinden sich in der Assembly Presentation- ̈ Vektorbasierte Grafiken Framework.dll. Zu ihnen zählen Klassen für Controls, Dokumente, Layout-Panels, Benutzer- Die Inhalte Ihrer Anwendung werden durch die WPF vektorbasiert gezeichnet. Somit ist führung und Animationen sowie Klassen zum Einbinden von Videos und Bildern. Oft wird Ihre Anwendung beliebig skalierbar und wirkt auch vergrößert nicht pixelig. diese Assembly allein als »die« WPF bezeichnet, da die anderen Assemblies, WindowsBase und PresentationCore, nur die Basis für ein UI-Framework bieten. Die WPF ist ein solches UI- Tipp Framework, das in der Assembly PresentationFramework implementiert ist. Ob eine WPF-Anwendung die Hardware voll ausnutzt, hängt von den Eigenschaften der Gra- In Kapitel 2, »Das Programmiermodell«, werden Sie sehen, dass die Assemblies Presenta- fikkarte und von der installierten DirectX-Version ab. Die WPF teilt Rechner aufgrund dieser tionCore.dll, PresentationFramework.dll und auch die Assembly WindowsBase.dll standard- Umstände in drei Ebenen ein: mäßig in Ihrem WPF-Projekt referenziert werden. ̈ Ebene 0 – Es ist DirectX kleiner als Version 7.0 installiert. Es findet somit keine Hard- warebeschleunigung statt. Das ganze Rendering (Zeichnen) findet in der Software statt. 1.3.5 Vorteile und Stärken der WPF-Architektur Das ist nicht sehr leistungsstark. ̈ Ebene 1 – eingeschränkte Hardwarebeschleunigung durch die Grafikkarte. DirectX ist Durch die Architektur der WPF und der darunterliegenden Komponente MilCore als Wrap- mindestens in der Version 7.0 installiert, aber in einer Version kleiner als 9.0. per um DirectX ergeben sich viele Vorteile gegenüber Windows Forms und älteren Win32- ̈ Ebene 2 – Fast alle Grafikfeatures der WPF verwenden die Hardwarebeschleunigung der Technologien. Die wichtigsten fasse ich an dieser Stelle kurz zusammen: Grafikkarte. Auf dem Rechner ist mindestens DirectX 9.0 installiert. ̈ Volle Ausnutzung der Hardware In einer WPF-Anwendung können Sie prüfen, auf welcher Ebene Ihre Anwendung läuft. Nut- Weil sie auf DirectX aufbauen, können WPF-Anwendungen die in heutigen Rechnern be- zen Sie dazu die statische Tier-Property der Klasse RenderCapability (Namespace: Sys- reits standardmäßig vorhandenen leistungsfähigen Grafikkarten voll ausnutzen. Falls die tem.Windows.Media). Die Tier-Property ist vom Typ int. Allerdings müssen Sie aus diesem Kraft der Grafikkarte nicht ausreicht, wird von Hardware- auf Software-Rendering umge- int das sogenannte High-Word extrahieren, damit Sie die eigentliche Ebene erhalten. Sie ex- stellt. trahieren ein High-Word (auch hWord genannt), indem Sie eine Bit-Verschiebung um 16 Bits ̈ Die WPF »zeichnet« selbst durchführen. Folgende Zeile zeigt, wie es geht: In einer WPF-Anwendung werden die visuellen Elemente durch die WPF gezeichnet und int ebene = RenderCapability.Tier >> 16; nicht durch das Betriebssystem, wie es in Windows Forms und älteren Win32-Technolo- Auf meinem Rechner enthält der Integer ebene den Wert 2. Meine Grafikkarte ist somit gut, gien der Fall war. Dies erlaubt zum einen verschiedene Effekte, wie die bereits erwähnte und es ist mindestens DirectX in der Version 9.0 installiert. Demnach findet bei WPF-Anwen- Transparenz. Neben solchen Effekten ist zum anderen durch das selbstständige Zeichnen dungen eine Hardwarebeschleunigung statt. der WPF die Anwendung des flexiblen Inhaltsmodells möglich, wodurch Sie visuelle Ele- mente beliebig ineinander verschachteln können. Zu guter Letzt können Sie, weil ja die Neben der Architektur baut die WPF auch auf spannenden Konzepten auf. So können Sie bei- WPF zeichnet, das visuelle Erscheinungsbild von Controls mit Styles und Templates Ihren spielsweise eine Benutzeroberfläche deklarativ mit der XML-basierten Beschreibungsspra- Wünschen entsprechend anpassen. che XAML erstellen. Einige dieser Konzepte, die uns Programmierern das Leben erleichtern ̈ Zwischengespeicherte Zeichnungsdaten sollen, werden im nächsten Abschnitt betrachtet. Durch die zwischengespeicherten Zeichnungsdaten eines visuellen Elements ist ein effek- tives Neuzeichnen möglich. Die Informationen des Visual Trees werden mit dem Compo- sition Tree abgeglichen, den MilCore zur Verfügung stellt. Ist ein Neuzeichnen notwendig, 1.4 Konzepte weil vielleicht ein anderes Fenster das Fenster Ihrer Applikation verdeckt hat, können dafür die im Composition Tree bereits vorhandenen zwischengespeicherten Zeichnungs- In Abschnitt 1.3, »Die Architektur der WPF«, haben Sie bereits einen kleinen Blick hinter die informationen verwendet werden. Auch Änderungen an einem visuellen Element – und Kulissen der WPF werfen können. In diesem Abschnitt erfahren Sie mehr über ein paar der somit an einem Knoten des Visual Trees – können sehr effizient neu gezeichnet werden. grundlegenden Konzepte der WPF, die auf der .NET-Seite verankert sind. Neben der deklara- Ändern Sie die Border-Linie eines Buttons, wird diese Änderung an MilCore übertragen tiven Sprache XAML sind dies unter anderem Dependency Properties, Routed Events, Com-
58 59 7201.book Seite 60 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 61 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
mands, Styles, Templates und 3D. Hier dargestellte und weitere Konzepte – wie Layout, Res- var btnOk = new System.Windows.Controls.Button 1 sourcen und Data Binding – werden in späteren Kapiteln separat betrachtet. An dieser Stelle { erhalten Sie lediglich einen kleinen Einblick. Es soll dabei (noch) nicht jedes Detail beleuchtet FontStyle = System.Windows.FontStyles.Italic, werden; betrachten Sie diesen Abschnitt somit als eine kleine Schnupperrunde, die Sie lo- Margin = new System.Windows.Thickness(10), cker angehen können. Content = "Ok" };
Listing 1.2 Ein Button in C# 1.4.1 XAML
Die Extensible Application Markup Language (XAML) ist eine XML-basierte Beschreibungs- Obwohl Sie Ihre Benutzeroberfläche auch rein in C# erstellen können – und dies in Ausnah- sprache, mit der Sie Objektbäume erstellen können. Zur Laufzeit werden aus den in XAML men bei komplexen Oberflächen manchmal auch sinnvoll ist –, profitieren Sie dann natür- deklarierten XML-Elementen .NET-Objekte erzeugt. lich nicht von den Vorteilen, die Ihnen XAML bietet: ̈ Sie können mit XAML die Darstellung Ihrer Anwendung besser von der dahinterliegen- Hinweis den Businesslogik trennen. Üblicherweise definieren Sie dazu in XAML die Beschreibung Mit anderen Worten: XAML ist ein Serialisierungsformat. Zur Laufzeit werden die Inhalte Ihrer Oberfläche und setzen die eigentliche Logik in eine Codebehind-Datei, die in einer einer XAML-Datei deserialisiert und die entsprechenden Objekte erzeugt. prozeduralen Sprache wie C# programmierte Methoden und Event Handler enthält. Das Prinzip der Codebehind-Datei kennen Sie vielleicht aus ASP.NET; auch dort werden Dar- Bei der WPF wird XAML für die Beschreibung von Benutzeroberflächen eingesetzt. Dafür de- stellung und Logik auf diese Weise getrennt. finieren Sie in XAML Controls, Styles, Animationen oder 3D-Objekte, um nur einige der Mög- ̈ Die Beschreibung einer Benutzeroberfläche in XAML ist wesentlich kompakter und über- lichkeiten zu nennen. Folgender Codeschnipsel stellt bereits einen gültigen XAML-Aus- sichtlicher als die Erstellung in C#. XAML schraubt somit die Komplexität Ihres Codes schnitt dar und erstellt einen Button mit kursiver Schriftart, einem Rand von 10 Einheiten nach unten. und dem Inhalt »OK«: ̈ Eine XAML-Datei ist ideales Futter für einen Designer, der Ihrer Benutzeroberfläche mit ̈ In XAML erstellte Benutzeroberflächen werden zur Designzeit stets aktuell im WPF- Listing 1.1 Beispiele\K01\01 Button\MainWindow.xaml Designer dargestellt. Für in C# erstellte Benutzeroberflächen gilt das dagegen nicht; diese sehen Sie erst zur Laufzeit. Event Handler und sonstige Logik werden üblicherweise in einer in C# geschriebenen Code- ̈ In XAML lässt sich jede öffentliche .NET-Klasse verwenden, die einen Default-Konstruktor behind-Datei eingefügt. Das Button-Element aus Listing 1.1 wird vom XAML-Parser der Klasse besitzt. Button aus dem CLR-Namespace System.Windows.Controls zugeordnet. Die Details werden ̈ Wenn Sie bereits mit Windows Forms und Visual Studio programmiert haben, dann wis- wir uns in Kapitel 3, »XAML«, genauer ansehen. Abbildung 1.7 zeigt den Button in einen Fens- sen Sie, dass in Visual Studio zu jeder Form Code vom Windows-Forms-Designer generiert ter. Der Button hat einem Rand von 10, kursive Schriftart und den Inhalt »OK«. wird. Seit .NET Framework 2.0 wird dieser generierte Code in eine partielle Klasse ausgela- gert. Sobald händisch etwas an diesem generierten Code geändert wird, hat der Windows- Forms-Designer meist Probleme, die Form wieder korrekt darzustellen, da er eine be- stimmte Formatierung des C#-Codes voraussetzt. In XAML besteht dieses Problem nicht: Sie können in XAML beliebige Änderungen durchführen, die sofort vom WPF-Designer dargestellt werden. Nehmen Sie umgekehrt Änderungen im WPF-Designer vor, werden Abbildung 1.7 Der erstellte Button diese gleich in XAML übernommen.
Wie Sie sehen, bietet XAML einige Vorteile gegenüber C#. Bedenken Sie jedoch, dass XAML Anstatt Ihre Benutzeroberflächen mit XAML zu definieren, ist natürlich auch der prozedura- die Sprache C# nicht ersetzen wird. XAML ist eine deklarative Sprache, in der Sie beispiels- le Weg mit C# möglich. Der XAML-Ausschnitt aus Listing 1.1 entspricht folgendem C#-Code:
60 61 7201.book Seite 62 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 63 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
weise keine Methoden definieren können. Dennoch eignet sich eine deklarative Sprache bes- ̈ Viele Dienste der WPF (wie Animationen oder Styles) lassen sich nur mit Dependency Prop- 1 tens für die Definition von Benutzeroberflächen. erties verwenden. Mit normalen Properties wäre es ohne weiteren Code nicht möglich, zu In Kapitel 3, »XAML«, werden wir XAML genau durchleuchten und uns die Syntax und Mög- bestimmen, welche Quelle (Animation, Style, lokaler Wert etc.) den endgültigen Wert lichkeiten dieser deklarativen, XML-basierten Sprache ansehen. An dieser Stelle wenden wir einer Dependency Property festlegt. uns einem weiteren Konzept zu, auf dem die WPF aufbaut, den Dependency Properties. ̈ Sie können als Attached Property implementiert auch auf anderen Elementen gesetzt werden.
1.4.2 Dependency Properties Aus Entwicklersicht besteht eine Dependency Property aus einer klassischen .NET-Property – wenn diese auch optional ist – und aus einem öffentlichen, statischen Feld vom Typ Depend- Dependency Properties sind eines der wichtigsten Konzepte der WPF. In der WPF lassen sich encyProperty. Dieses Feld stellt den Schlüssel zum eigentlichen Wert der Property dar. Properties auf verschiedene Arten setzen: entweder auf dem üblichen Weg direkt auf einem Objekt in C#, in XAML oder über Styles, Data Binding oder Animationen. Einige Properties public class MyClass:DependencyObject werden sogar durch eine Eltern-Kind-Beziehung »vererbt«. Ändern Sie den Wert der Font- { Size-Property eines Window-Objekts, wird der gesetzte Wert wie von Geisterhand – im Hinter- public static readonly DependencyProperty FontSizeProperty grund hat natürlich die WPF ihre Hände im Spiel – auch von im Fenster enthaltenen Button- = DependencyProperty.Register("FontSize" und TextBox-Objekten verwendet. ,typeof(double) ,typeof(Button) Eine Dependency Property ist also von mehreren Quellen in Ihrer Anwendung und im Sys- ,new FrameworkPropertyMetadata(11.0 tem abhängig – daher der Name »Dependency« (dt. »Abhängigkeit«). Wenn eine Depend- ,FrameworkPropertyMetadataOptions.Inherits ency Property nicht gesetzt ist, hat sie einen Default-Wert. |FrameworkPropertyMetadataOptions.AffectsRender)); Dependency Properties sind bei der WPF die Grundlage für Styles, Animationen, Data Bind- public double FontSize ing, Property-Vererbung und vieles mehr. Mit einer normalen .NET-Property können Sie kei- { nen Gebrauch von diesen »Diensten« der WPF machen. Glücklicherweise sind die meisten get { return (double)GetValue(FontSizeProperty); } Properties der Elemente der WPF als Dependency Properties implementiert und lassen sich set { SetValue(FontSizeProperty, value); } somit mit Animationen, Data Bindings oder Styles verwenden. } } Die wohl wichtigste Eigenschaft einer Dependency Property ist ihr integrierter Benachrichti- gungsmechanismus für Änderungen, wodurch die WPF beobachten kann, wann sich ihr Listing 1.3 Implementierung einer Dependency Property Wert ändert. Dies macht sie auch als Quelle für ein Data Binding ideal. Die Methoden GetValue und SetValue, die in Listing 1.3 in den get- und set-Accessoren der Dependency Properties werden in der Laufzeitumgebung der WPF in der sogenannten Prop- .NET-Property aufgerufen werden, sind in der Klasse DependencyObject definiert, von der die erty Engine registriert, die die Grundlage für diverse Möglichkeiten ist, wie etwa die Property- dargestellte Klasse erbt. Jede Klasse, die Dependency Properties speichern möchte, muss von Vererbung. DependencyObject abgeleitet sein. Zusammengefasst bieten Dependency Properties folgenden Mehrwert gegenüber klassi- Der obere Codeausschnitt soll Ihnen nur eine kleine Vorstellung davon geben, wie die Imple- schen .NET-Properties: mentierung einer Dependency Property aussieht. In Kapitel 7, »Dependency Properties«, ̈ Sie verfügen über einen integrierten Benachrichtigungsmechanismus. werden wir diese Implementierung ausführlich betrachten. Denken Sie an dieser Stelle noch ̈ Sie besitzen einen Default-Wert. an das Motto dieses Kapitels: »Lehnen Sie sich zurück«. Wir werden uns später alles noch ̈ Sie besitzen Metadaten, die unter anderem die Information enthalten, ob durch eine Än- sehr genau anschauen. derung des Wertes ein Neuzeichnen des visuellen Elements notwendig ist. Auf den ersten Blick werden Sie aufgrund der Kapselung durch eine normale .NET-Property ̈ Sie verfügen über eine integrierte Validierung. nicht bemerken, dass Sie auf eine Dependency Property zugreifen. Beispielsweise ist die ̈ Sie bieten Property-Vererbung über den Visual Tree. FontSize-Property der Button-Klasse als Dependency Property implementiert, die sich auf-
62 63 7201.book Seite 64 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 65 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
grund der Kapselung durch eine »normale« .NET-Property auch wie eine solche verwenden Nimmt das Grid nun das Layout vor, so kann es auf jedem einzelnen Element die Grid.Row 1 lässt: durch Aufruf von GetValue abfragen und so die Elemente in die entsprechende Zeile setzen. var btn = new System.Windows.Controls.Button(); Abbildung 1.8 zeigt das Grid aus Listing 1.4 in einem Fenster. btn.FontSize = 15.0;
Hinweis Im Gegensatz zu einer normalen .NET-Property kann die als Dependency Property implemen- tierte FontSize in Animationen oder Styles verwendet werden.
Neben der Kombination eines statischen Feldes vom Typ DependencyProperty mit einer nor- malen .NET-Property als Wrapper treten Dependency Properties auch als Attached Proper- ties auf. Das Besondere an einer Attached Property ist, dass sie Teil einer Klasse ist, aber auf Abbildung 1.8 Durch die Attached Properties werden hier eine TextBox und Objekten anderer Klassen gesetzt wird. Dies mag zunächst etwas verwunderlich klingen, ein Button in einem Grid untereinander in zwei Zeilen angeordnet. wird aber insbesondere bei Layout-Panels verwendet. Kindelemente müssen somit nicht mit unnötig vielen Eigenschaften für jedes Layout-Panel überladen werden, da die Defini- Obwohl Sie Dependency Properties wahrscheinlich meist nur bei der Implementierung eige- tion der Dependency Properties im Panel selbst liegt. Wie kann das gehen? ner Controls benötigen, trägt ihr Verständnis natürlich zu einem effektiveren Umgang mit der WPF bei. Beim Einstieg in die WPF sorgen Dependency Properties bei den meisten Ent- Das Panel definiert nur den Schlüssel für einen Wert. Dieser Schlüssel ist ein statisches Feld wicklern für Missverständnisse und manchmal auch für etwas Frust. Dies liegt meist daran, vom Typ DependencyProperty. Objekte, die Dependency Properties speichern, müssen zwin- dass am Anfang nicht ganz klar ist, wofür die Dependency Properties letztlich gut sind. So gend vom Typ DependencyObject sein. Diese Klasse enthält vereinfacht gesehen eine Art lassen sie das Bild von .NET ein wenig komplizierter erscheinen. Sehen Sie sich nochmals den Hashtable, in der mit der Methode SetValue Schlüssel/Wert-Paare gespeichert werden. Alle Mehrwert von Dependency Properties gegenüber klassischen .NET-Properties am Anfang Controls der WPF leiten von dieser Klasse ab und besitzen somit intern eine solche Art Hash- dieses Abschnitts an. Behalten Sie an dieser Stelle im Hinterkopf, dass Sie die in der WPF table. Möchten Sie auf einem Button eine Layout-Property speichern, so wird der Wert in der integrierten Animationen, Styles und vieles mehr nur mit Dependency Properties verwen- Hashtable des Button-Objekts unter dem in der Panel-Klasse definierten Schlüssel gespei- den können. Auch das Prinzip der Attached Properties – die Sie unter anderem in Kapitel 6, chert. Nimmt das Panel-Objekt das Layout vor, so kann es mit dem Schlüssel die für das Lay- »Layout«, noch öfter sehen werden – ist nur dank Dependency Properties möglich. out benötigten Werte der einzelnen Controls abrufen. Da die Dependency Properties ein zentrales Element der WPF sind, dieser Abschnitt sicher ei- XAML definiert für die Attached Properties eine eigene Syntax. In Listing 1.4 wird ein Grid nige Fragen offen lässt und Ihren Wissensdurst in Sachen Dependency Properties gewiss und mit zwei Zeilen definiert. Ein Grid ist eines der Layout-Panels der WPF, das Elemente in Zei- hoffentlich nicht gestillt hat, ist ihnen in diesem Buch ein eigenes Kapitel gewidmet. In Kapi- len und Spalten anordnet. Im Grid in Listing 1.4 wird eine TextBox der ersten und ein Button tel 7, »Dependency Properties«, werden Sie alle Details zu Dependency Properties und ihrer der zweiten Zeile zugeordnet. Dazu wird die in der Klasse Grid als Attached Property imple- Implementierung erfahren. mentierte Grid.Row auf der TextBox und auf dem Button gesetzt:
64 65 7201.book Seite 66 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 67 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
Stellen Sie sich vor, was passiert, wenn ein Benutzer auf das im StackPanel der Button- Panel, auf dem Button und auf dem Rectangle wurden Event Handler für die Events Pre- 1 Instanz enthaltene Rectangle klickt. Bekommt der Button dann auch eine Benachrichtigung viewMouseLeftButtonDown und MouseLeftButtonDown installiert, die das Event und den Sender über das ausgelöste MouseLeftButtonDown-Event? In bisherigen Programmiermodellen wird in einer ListView ausgeben. er nicht benachrichtigt, denn bisher war es so, dass das Element, das im Vordergrund steht und auf dem der Fokus liegt, auch das Event empfängt – in diesem Fall das MouseLeftBut- tonDown-Event. Preview Button In der WPF ist die klassische Behandlung von Events nicht ausreichend, da sich auch einfa- che Controls wie ein Button aus mehreren anderen visuellen Elementen zusammensetzen und nach dem klassischen Prinzip diese Elemente das Event absorbieren würden. Der Button Preview StackPanel Tunneling
selbst erhielte somit eventuell gar keine Information darüber, dass etwas »in ihm« geklickt Bubbling wurde. Um zu unserem Button mit einem StackPanel und einem Rectangle zurückzukom- men, bedeutet dies, dass der Button, wenn ein Benutzer auf das Rectangle oder das Stack- Preview Rectangle Panel klickt, nach klassischem Event Handling selbst kein MouseLeftButtonDown-Event mitbe- kommt. Und genau das ist der Punkt, an dem die Routed Events der WPF ins Spiel kommen. Routed Events können bei der WPF eine von drei verschiedenen Routing-Strategien verwen- Abbildung 1.9 Bei der WPF werden Routed Events im Element Tree von oben nach unten getunnelt den: und blubbern von unten nach oben. ̈ Tunnel – Das Event wird von oben durch den Visual Tree in niedrigere Hierarchiestufen geroutet. In Abbildung 1.10 wurde direkt auf das Rectangle geklickt. Die ListView unterhalb des But- tons wird anschließend durch die Event Handler auf den einzelnen Elementen mit Event- ̈ Bubble – Das Event »blubbert« von einem im Visual Tree tiefer liegenden Element nach Informationen gefüllt. Darin lässt sich gut erkennen, wie das PreviewMouseLeftButtonDown- oben. Event vom Window bis zum Rectangle getunnelt wird. Anschließend blubbert das Mouse- ̈ Direct – Das Event wird nur auf dem geklickten visuellen Element ausgelöst. Diese Strate- LeftButtonDown-Event vom Rectangle im Element Tree nach oben zurück zum Window. gie gleicht der bei Events, die Sie aus der bisherigen Programmierung mit .NET 2.0 und früher kennen – mit der Ausnahme, dass sich diese Events auch in einem sogenannten EventTrigger verwenden lassen.
Das MouseLeftButtonDown-Event der WPF besitzt die Strategie Bubble. Wird in unserem Button auf das Rectangle geklickt, »blubbert« das Event nach oben zum StackPanel und von dort zum Button. Der Button selbst löst beim Empfang des MouseLeftButtonDown-Events sein eige- nes Click-Event aus, das auch die Bubble-Strategie besitzt und weiter nach oben blubbert. Tunneling Events und Bubbling Events treten oft in Paaren auf. So gibt es zum Bubbling Event MouseLeftButtonDown ein passendes Gegenstück, das Tunneling Event PreviewMouse- LeftButtonDown. Abbildung 1.9 verdeutlicht den Button und das darin enthaltene StackPanel mit dem Rectangle als Inhalt. Sie sehen, wie zuerst die Tunneling Events – konventions- gemäß mit dem Präfix »Preview« benannt – von oben nach unten und wie anschließend die Bubbling Events von unten nach oben ausgelöst werden. Jedes Element, das auf dieser Route liegt, kann beispielsweise für das MouseLeftButtonDown-Event einen Event Handler installie- ren. In Abbildung 1.10 sehen Sie ein Fenster, das unseren Button enthält. Im Button ist ein Stack- Abbildung 1.10 Das Event wird vom MainWindow bis zum geklickten roten Rectangle getunnelt und blubbert wieder nach oben zum MainWindow. Panel (schwarz), das wiederum ein Rectangle (rot) enthält. Auf dem Window, auf dem Stack-
66 67 7201.book Seite 68 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 69 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
In Abbildung 1.11 sehen Sie, wie das Event geroutet wird, wenn nicht auf das rote Rectangle, 1.4.4 Commands 1 sondern auf das schwarze StackPanel geklickt wird. Ein weiteres Konzept der WPF ist die integrierte Infrastruktur für Commands. Im Gegensatz zu Events erlauben Commands eine bessere Trennung der Präsentationsschicht von der An- wendungslogik. Sie geben auf einem Element in XAML nicht direkt einen Event Handler an, sondern lediglich ein Command. Stellen Sie sich vor, Sie werden beauftragt, einen kleinen Texteditor zu programmieren. Darin benötigen Sie unter anderem Funktionalität zum Ausschneiden, Kopieren und Einfü- gen von Text. Typischerweise kann ein Benutzer diese Funktionen aus dem Menü, dem Kon- textmenü oder der Toolbar aufrufen. In unserem Beispiel soll es der Einfachheit halber je Funktion ein MenuItem wie auch einen Button geben. Klassischerweise würden Sie für jedes MenuItem und jeden Button einen Event Handler im- plementieren, der die entsprechende Funktion ausführt. Haben Sie den Event Handler für das Ausführen des Kopierens auf dem MenuItem und auch auf dem Button erstellt, so müs- sen Sie darüber hinaus Ihre Controls entsprechend aktivieren und deaktivieren. Denn nur, wenn Text in der Textbox markiert ist, sollen die Controls für die Kopierfunktionalität auch Abbildung 1.11 Das Event wird vom MainWindow bis zum geklickten schwarzen aktiviert sein. Auch dies lässt sich mit den entsprechenden Event Handlern ausprogrammie- StackPanel getunnelt und blubbert wieder nach oben zum MainWindow. ren. Neben dem Aktivieren und Deaktivieren möchten Sie eventuell die Tastenkombinatio- nen (Strg)+(C) unterstützen. Hier ist ebenso ein weiterer Event Handler notwendig, der auf Ähnlich wie bei den mithilfe von Dependency Properties implementierten Attached Proper- das KeyDown-Event reagiert und das entsprechende Kopieren des markierten Textes in die ties lassen sich Routed Events auch auf visuellen Elementen setzen, die das Routed Event Zwischenablage auslöst. nicht selbst definieren. Es wird dann von Attached Events gesprochen. Wenn Sie ein weiteres Control zu Ihrem Texteditor hinzufügen, das die Copy-Funktionalität Stellen Sie sich folgendes simples Beispiel vor: Sie haben ein Fenster, das neun Buttons ent- unterstützen soll (beispielsweise einen Button in einer Toolbar), dann müssen Sie auch für hält. Jeder Button soll beim Klicken eine Messagebox mit einer String-Repräsentation seines dieses Control wieder alle Event Handler installieren und dafür sorgen, dass das Control rich- Inhalts anzeigen. Mit gewöhnlichen Events installieren Sie für diese Aufgabe pro Button tig aktiviert und deaktiviert wird. Möchten Sie die Controls, die an der Kopierfunktionalität einen Event Handler für das Click-Event, oder Sie verwenden einen gemeinsamen Event teilnehmen, nicht fest in Ihrem Code verdrahten, wartet schon mehr Aufwand auf Sie. Handler, den Sie dennoch mit dem Click-Event jedes Buttons verbinden müssen. Glücklicherweise gibt es in der WPF eine eigene Infrastruktur für Commands, die Ihnen Wie Sie bereits erfahren haben, besitzt das Click-Event die Strategie Bubble. Somit haben Sie genau solche Aufgaben wesentlich erleichtert und Ihnen im Gegensatz zu den Events eine die Möglichkeit, nur einen Event Handler für das Button.ClickEvent auf dem Window-Objekt bessere Entkopplung Ihrer Benutzeroberfläche von der Anwendungslogik erlaubt. Klären zu installieren. Wird auf einen Button geklickt, blubbert das Click-Event vom Button nach wir zunächst, was ein Command überhaupt ist. Bei einem Command handelt es sich um ein oben zum Window-Objekt. Das Window-Objekt erhält das Event und ruft den Event Handler Objekt einer Klasse, die das Interface ICommand (Namespace: System.Windows.Input) imple- auf. Allerdings befindet sich in der sender-Variablen des Event Handlers immer das Window- mentiert, das die Methoden Execute und CanExecute und das Event CanExecuteChanged defi- Objekt. Sie erhalten über die Source-Property der bei Routed Events verwendeten Routed- niert: EventArgs eine Referenz auf den geklickten Button und können so die MessageBox mit dem ̈ Namen anzeigen. Execute löst das Command aus. ̈ CanExecute gibt einen booleschen Wert zurück, der angibt, ob das Command überhaupt Wie Sie sehen, eröffnen sich Ihnen mit Routed Events interessante neue Möglichkeiten. In ausgelöst werden kann. Kapitel 8, »Routed Events«, erfahren Sie alle notwendigen Details zu Routed Events und ler- ̈ nen, wie Sie Routed Events in eigenen Klassen implementieren. CanExecuteChanged wird ausgelöst, wenn CanExecute beim nächsten Aufruf vermutlich einen anderen Wert zurückgibt.
68 69 7201.book Seite 70 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 71 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
Einem Button können Sie ein ICommand-Objekt über die Command-Property zuweisen. Das ICom- mands.Copy ein CommandBinding definiert, das im CanExecute-Event die Property CanExecute der 1 mand wird automatisch ausgelöst, sobald Sie auf den Button klicken. Gibt die CanExecute- CanExecuteEventArgs auf false setzt, falls in der Textbox kein Text markiert ist. Wird das Methode des Commands false zurück, so wird die IsEnabled-Property des Buttons automa- ApplicationCommands.Copy ausgeführt, wird im Executed-Event-Handler des in der TextBox tisch auf false gesetzt. enthaltenen CommandBindings der selektierte Text in die Zwischenablage kopiert. Mit der Klasse RoutedCommand besitzt die WPF bereits eine pfannenfertige ICommand-Imple- Die in den Controls der WPF bereits vordefinierten CommandBinding-Instanzen erlauben es Ih- mentierung. Es gibt bereits vordefinierte RoutedCommand-Objekte. So besitzt die Klasse Appli- nen, einen funktionsfähigen Texteditor ohne prozeduralen Code rein in XAML zu erstellen cationCommands statische Properties wie Copy oder Paste, die RoutedCommand-Instanzen enthal- (siehe Listing 1.5). ten. Der Knackpunkt bei den Routed Commands ist, dass eine RoutedCommand-Instanz die
70 71 7201.book Seite 72 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 73 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.4 Konzepte
72 73 7201.book Seite 74 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 75 Donnerstag, 5. September 2019 8:43 08
1 Einführung in die WPF 1.5 Zusammenfassung
Mit Visual Studio 2019 lassen sich WPF-Anwendungen für .NET Framework und .NET Core er- 1 stellen. Während bisherige Programmiermodelle unter Windows nur dünne Wrapper um die Windows-API waren – so auch Windows Forms –, ist die WPF eine UI-Bibliothek, die in .NET entwickelt wurde und nicht mehr auf der Windows-API aufbaut, sondern Inhalte selbst via
Hinweis Benutzeroberflächen können Sie nur aus XAML, nur aus C# (oder einer anderen prozedura- len Sprache wie VB.NET) oder aus einer Mischung aus XAML und C# (in einer Codebehind- Obwohl die 3D-API der WPF auf DirectX aufbaut, ist sie nicht zum Entwickeln von Spielen ge- Datei) erstellen. dacht. Dafür sollten Sie Managed DirectX verwenden, das wesentlich performanter ist. Die 3D-API der WPF ist allerdings ein recht einfaches Mittel, um Ihrer Anwendung mit 3D-Effek- Im nächsten Kapitel werden wir uns das Programmiermodell der WPF ansehen. Sie werden ten etwas Pep zu verleihen oder um beispielsweise Geschäftsdaten in 3D darzustellen. unter anderem die wichtigsten Klassen der WPF kennenlernen, und wir werden die erste Windows-Anwendung mit der WPF implementieren.
1.5 Zusammenfassung
Die WPF ist ein umfangreiches Programmiermodell, mit dem sich professionelle Desktop- Anwendungen entwickeln lassen. Die WPF wird im .NET Framework ab Version 3.0 und auch in .NET Core ab Version 3.0 unterstützt. .NET Core ist die Zukunft, und neue WPF-Anwendun- gen sollten mit .NET Core entwickelt werden.
74 75 7201.book Seite 142 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 143 Donnerstag, 5. September 2019 8:43 08
Kapitel 3 XAML 3
XAML (sprich: »Semmel«) ist eine XML-basierte Beschreibungssprache. Sie wird in der WPF und in UWP/WinUI zur Definition von Benutzeroberflächen einge- setzt. In diesem Kapitel erfahren Sie mehr über die Syntax und die Funktions- weise von XAML.
Die Extensible Application Markup Language (XAML) wurde zusammen mit der WPF einge- führt. XAML ist eine XML-basierte Beschreibungssprache, die bei der WPF zur Erstellung von Benutzeroberflächen eingesetzt wird. Obwohl mit dem Programmiermodell der WPF das Design der Benutzeroberfläche auch allein in C# erstellt werden kann, ist XAML die be- vorzugte Art. Der ausschlaggebende Grund ist, dass XAML eine bessere Trennung von Be- nutzeroberflächendesign und -logik ermöglicht. Allerdings muss vorweg gesagt werden, dass Sie in XAML nichts tun können, was nicht auch in C# möglich ist. XAML ist lediglich ein Serialisierungsformat. Zur Laufzeit werden aus den in XAML angegebenen Elementen Objekte erzeugt. Warum XAML dennoch eingeführt wurde, erfahren Sie in Abschnitt 3.1, »
3.1
Im Entwicklungsprozess einer Anwendung wird meist zu Beginn festgelegt, wie die fertig im- plementierte Benutzeroberfläche aussehen soll. Im traditionellen Entwicklungsprozess ist eine Person – die im Weiteren als »Designer« bezeichnet wird – dafür zuständig, das Design der Benutzeroberfläche mithilfe eines Werkzeugs festzulegen, zum Beispiel mit einem Gra- fikprogramm. Das Ergebnis ist ein Entwurf der Benutzeroberfläche, der in irgendeiner Form gespeichert wird, etwa als Bilddatei.
143 7201.book Seite 144 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 145 Donnerstag, 5. September 2019 8:43 08
3XAML 3.2 Elemente und Attribute
Die erstellten Dateien gibt der Designer an den Entwickler weiter. Dieser hat nun die Auf- gabe, die Anwendungslogik zu implementieren und die Benutzeroberfläche gemäß dem Tipp Entwurf umzusetzen, den er vom Designer erhalten hat. Der Entwickler baut in Visual Studio Da sich mit Blend auch .csproj-Dateien öffnen lassen, ist es oft auch üblich, dass ein Entwick- die vom Designer entworfene Benutzeroberfläche nach. Dabei versucht er, das Design zu ler Visual Studio und Blend parallel betreibt und in beiden Programmen dasselbe Projekt ge- 3 treffen, das vom Designer spezifiziert wurde. öffnet hat. In Blend kann er dann auf einfache Weise Farbverläufe, Animationen oder Tem- Der Entwickler erledigt also nochmals die ganze Arbeit, die der Designer bereits getan hat. plates anpassen. Visual Studio merkt automatisch, dass sich die Dateien außerhalb von Visual Studio geändert haben, und lädt sie bei Bedarf neu. Dabei trifft er in der Praxis mit seinem Design der Benutzeroberfläche oft nicht die Vorstel- lungen des Designers. Insbesondere, wenn eine komplexe Benutzeroberfläche mit visuellen Mit der Aufteilung in Designer und Entwickler hat sich für die Architektur von WPF-Anwen- Effekten und Animationen entworfen wird, kann es zu vielen Missverständnissen zwischen dungen ein Pattern bewährt, das auf dem Model-View-Controller aufbaut. Das sogenannte Designer und Entwickler kommen. Dabei ist es die doppelte Erfassung des Designs der Be- Model-View-ViewModel-Pattern (MVVM) ermöglicht die beste Trennung von UI und Logik. In nutzeroberfläche – einmal durch den Designer und ein zweites Mal durch den Entwickler –, Abschnitt 9.6, »Das Model-View-ViewModel-Pattern (MVVM)«, finden Sie mehr Informatio- die im Entwicklungsprozess zu Reibungen führt. Aufgrund unterschiedlicher Formate ist die nen zum MVVM-Pattern und eine kleine Beispielanwendung, die dieses Pattern einsetzt. doppelte Erfassung leider nicht vermeidbar. Ein gemeinsames Format würde Abhilfe schaf- fen. Außer seiner Funktion als Austauschformat zwischen Designer und Entwickler bietet XAML gegenüber der prozeduralen Programmierung einer Benutzeroberfläche weitere Vorteile. Genau an dieser Stelle kommt XAML ins Spiel. Als deklarative Beschreibungssprache für Be- An dieser Stelle sind die wichtigsten: nutzeroberflächen verbessert XAML die Zusammenarbeit, indem es als Austauschformat ̈ dient. Sie benötigen weitaus weniger Code als in C#. Darüber hinaus lässt sich die Benutzerober- fläche einfacher und schneller implementieren, da XAML leicht lesbar und besser struktu- Bei der Entwicklung mit der WPF erstellt der Designer die Benutzeroberfläche in einem De- rierbar ist als prozeduraler Code. signwerkzeug. Aus diesem Designwerkzeug exportiert er XAML. Mittlerweile besitzen viele ̈ XAML ist ein vertrautes Konzept. Wenn Sie über Erfahrung mit HTML oder anderen web- Anwendungen eine Exportfunktion für XAML, sei es standardmäßig oder über ein Plug-in. basierten Beschreibungssprachen verfügen, werden Sie sich in XAML relativ schnell zu- Beispielsweise lässt sich auch aus Adobe Illustrator XAML exportieren. Microsoft stellt für rechtfinden. Allerdings möchte ich XAML nicht mit Sprachen wie HTML vergleichen. Designer unter anderem das Programm Blend zur Verfügung, das mit Visual Studio instal- XAML ist im Grunde ein zusätzlicher Weg, um .NET-Objekte zu erzeugen. liert wird. In diesem Programm findet der Designer typische Grafikwerkzeuge wieder, mit ̈ denen er die Benutzeroberfläche erstellen und als XAML abspeichern kann. XAML ist erweiterbar (»extensible«). Sie können beispielsweise in XAML Objekte von Ihren eigenen Klassen erstellen. Die vom Designer als XAML gespeicherte Benutzeroberfläche importiert der Entwickler in ̈ Visual Studio. Er muss die Benutzeroberfläche nicht wie im traditionellen Entwicklungspro- Neben Microsoft bieten viele Dritthersteller in ihren Programmen Unterstützung für zess nochmals erstellen, sondern kann direkt die XAML-Datei des Designers verwenden und XAML an. An dieser Stelle seien Adobe Illustrator und Zam3D von Electric Rain erwähnt. diese nun mit der dazugehörigen Logik versehen, die er in C# implementiert. ̈ Eine XAML-Datei ist eine XML-basierte Repräsentation von .NET-Objekten. Es gibt somit keinen Performance-Nachteil gegenüber einer Implementierung der Benutzeroberfläche In der Praxis hat sich auch oft der umgekehrte Weg bewährt. Dabei erstellt der Entwickler im in C#. Jede .NET-Klasse können Sie in XAML verwenden, wenn die Klasse einen öffent- ersten Schritt die Anwendung mit vollständiger Logik und einem rudimentären GUI. Die lichen Default-Konstruktor (parameterlos) besitzt. ganze Anwendung gibt er im zweiten Schritt an den Designer weiter. Dieser öffnet in seinem ̈ Design-Tool Blend das erhaltene Projekt (.csproj oder .vbproj). Der Designer verschönert in Sie können eine XAML-Datei zur Laufzeit dynamisch laden, um die darin deklarierten Ob- Blend das GUI mit neuen Templates für die Controls, fügt hier und da eine Animation ein, jekte in Ihrer Anwendung zu nutzen. verbindet eventuell Teile der GUI mittels Data Binding mit der vom Entwickler implemen- tierten Logik, erstellt Farbverläufe für den Hintergrund etc., bis er schließlich das gewünsch- te Design getroffen hat. 3.2 Elemente und Attribute
In weiteren Schritten öffnet der Entwickler das Projekt wieder in Visual Studio und führt XAML basiert auf XML und besteht somit aus XML-Elementen und XML-Attributen. Wie seine Unit Tests durch, um zu sehen, ob der Designer nicht versehentlich seine Programm- XML-Dokumente müssen auch XAML-Dokumente wohlgeformt sein. Wohlgeformt ist eine logik manipuliert hat.
144 145 7201.book Seite 146 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 147 Donnerstag, 5. September 2019 8:43 08
3XAML 3.3 Namespaces
XAML-Datei genau dann, wenn sie einige Voraussetzungen erfüllt. Die wichtigsten Voraus- Der XAML-Code aus Listing 3.1 entspricht folgendem Code in C#: setzungen sind: var w = new System.Windows.Window(); ̈ Eine XAML-Datei hat genau ein Wurzelelement, das alle anderen Elemente umschließt. var b = new System.Windows.Controls.Button(); 3 ̈ Auf ein öffnendes Element folgt ein schließendes Element, wie die Überschrift von Ab- b.Content = "OK"; schnitt 3.1, »
146 147 7201.book Seite 148 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 149 Donnerstag, 5. September 2019 8:43 08
3XAML 3.3 Namespaces
3.3.1 Der XML-Namespace der WPF assemblies[2] = typeof(Dispatcher).Assembly; // WindowsBase assemblies[3] = typeof(WindowsFormsHost).Assembly; // WindowsFormsIntegration In Listing 3.1 wurden in XAML ein Window-Element und ein Button-Element deklariert. Zur var list = new List
148 149 7201.book Seite 150 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 151 Donnerstag, 5. September 2019 8:43 08
3XAML 3.3 Namespaces
3.3.3 Über den Namespace-Alias System.Windows.Shapes System.Windows.Shell Der XML-Namespace der WPF ist in einem XAML-Dokument immer der Default-Namespace. Der Default-Namespace ist jener, der kein Alias besitzt. Dies ist sinnvoll, da der Großteil der Da die Beziehung zwischen dem XML-Namespace der WPF und den zugeordneten CLR- 3 Namespaces eine 1:n-Beziehung ist, mussten die Entwickler der WPF strikt darauf achten, Elemente in einer XAML-Datei aus dem XML-Namespace der WPF stammt und somit nicht dass die Klassennamen über alle zugeordneten CLR-Namespaces hinweg eindeutig sind. An- mit einem Alias als Präfix versehen werden muss. Dennoch können Sie natürlich auch für sonsten könnte ein Objektelement in XAML nicht eindeutig einer Klasse zugeordnet werden. den XML-Namespace der WPF ein beliebiges Alias setzen, was der Ausschnitt aus Listing 3.4 Daher gibt es in den CLR-Namespaces, die dem XML-Namespace der WPF zugeordnet sind, zeigt: beispielsweise nur im Namespace System.Windows.Controls eine Button-Klasse.
Der XML-Namespace für XAML ist mit dem XmlnsDefinitionAttribute dem CLR-Namespace Elemente, die kein Präfix besitzen, sind immer dem Default-Namespace zugeordnet, der ein- System.Windows.Markup zugeordnet. Neben den Klassen aus diesem CLR-Namespace verfügt fach ohne Alias mit xmlns=... gesetzt wird. Wie Listing 3.4 zeigt, ordnen Sie ein Element der XML-Namespace von XAML über spezielle Direktiven für den XAML-Compiler und -Par- einem anderen Namespace als dem Default-Namespace zu, indem Sie folgende Syntax ver- ser. Diese Direktiven werden auch XAML-Spracherweiterungen genannt und sehen im XAML- wenden: Dokument auf den ersten Blick wie Properties auf Objektelementen aus. Tatsächlich sind es
150 151 7201.book Seite 152 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 153 Donnerstag, 5. September 2019 8:43 08
3XAML 3.3 Namespaces
der XAML-Parser versteht. Aus der speziellen Syntax erkennt der XAML-Parser den zugeord- neten CLR-Namespace wie auch die Assembly, die den CLR-Namespace enthält. Die Syntax sieht wie folgt aus: Listing 3.5 Beispiele\K03\04 CustomNamespacesInXAML\MainWindow.xaml 3 xmlns:mn="clr-namespace:MeinCLRNamespace;assembly=MeineAssembly" mn ist das frei wählbare Alias für den zugeordneten CLR-Namespace. Objekte aus dem CLR- In Listing 3.5 wird im Window eine ListBox erstellt. Die ListBox wird mit einem String-Objekt Namespace MeinCLRNamespace lassen sich in XAML nun mit Objektelementen in der Form und einem Objekt der Klasse RepeatString gefüllt. RepeatString liegt im Namespace Custom- von
152 153 7201.book Seite 154 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 155 Donnerstag, 5. September 2019 8:43 08
3XAML 3.4 Properties in XAML setzen
Das in Listing 3.5 deklarierte Window-Objekt zeigt den Inhalt wie vermutet an. Das ebenfalls in XAML erstellte RepeatString-Objekt wiederholt den angegebenen String Hallo zweimal, was Hinweis zu der Ansicht aus Abbildung 3.1 führt. Sinnvoll ist die Definition eines XML-Namespaces ohne Alias (xmlns="...") auf einem Objekt- element anstelle eines XML-Namespaces mit Alias (xmlns:alias="...") auf dem Wurzel- 3 element genau dann, wenn das Objektelement viele weitere Objektelemente enthält, die im gleichen XML-Namespace wie das Objektelement selbst liegen. Dadurch können Sie sich ei- nige Aliasse als Präfix auf den Objektelementen sparen. Würde in einem solchem Fall der XML-Namespace auf dem Wurzelelement mit dem Alias angelegt, müssten alle Elemente in Abbildung 3.1 Das Window-Objekt aus Listing 3.5 in Aktion diesem Objektelement mit einem Alias versehen werden.
Das Beispiel zeigt, dass sich weitere Assemblies und CLR-Namespaces leicht in XAML einbin- den lassen. 3.4 Properties in XAML setzen Tipp Wird auf einem Element in XAML ein XML-Attribut definiert, wird dieses entweder einer Prop- Falls Sie beispielsweise ein Framework entwickeln, können Sie auf den Assemblies Ihres erty oder einem Event zugeordnet. Mit einem XML-Attribut lässt sich also eine Property set- Frameworks natürlich auch XmlnsDefinitionAttributes definieren, die XML-Namespaces zen. XAML bietet neben dieser sogenannten Attribut-Syntax weitere Möglichkeiten, Proper- CLR-Namespaces zuordnen. Referenziert der Benutzer Ihres Frameworks Ihre Assemblies, ties zu setzen. In diesem Abschnitt sehen wir uns die folgenden Möglichkeiten an: muss er nur noch den XML-Namespace angeben. So ist das ja auch bei den Klassen der WPF ̈ der Fall. die Attribut-Syntax – Auf einem Element wird ein XML-Attribut definiert, das die .NET- Property setzt. Obwohl die xmlns-Attribute üblicherweise auf dem Wurzelelement erstellt werden, können ̈ die Property-Element-Syntax – Es wird speziell für eine Property ein eigenes XML-Ele- Sie auch auf Kindelementen xmlns-Attribute setzen. Das in Listing 3.7 deklarierte Window- ment erstellt. Dieses XML-Element ist jetzt kein Objektelement, sondern ein Property-Ele- Objekt ist analog zu dem in Abbildung 3.1 dargestellten. ment, da es einer Property zugeordnet wird. Diese Syntax erlaubt es, einer Property ein komplexes Objekt zuzuweisen.
154 155 7201.book Seite 156 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 157 Donnerstag, 5. September 2019 8:43 08
3XAML 3.4 Properties in XAML setzen
Die Syntax, die oben zum Setzen der Content-Property verwendet wurde, wird als Attribut- Syntax bezeichnet. Wie an der Attribut-Syntax zu erkennen ist, lässt sich der Content-Proper- Hinweis ty ein String-Wert zuweisen. Wenn die Property einen primitiven Typ (bool, int, double, Am Anfang dieses Kapitels wurde beschrieben, dass in XAML Elemente .NET-Klassen zuge- float, char etc.) oder einen Aufzählungswert verlangt, wird der in der Attribut-Syntax ange- ordnet werden. Attribute werden .NET-Properties und -Events zugeordnet. Die Property-Ele- 3 gebene String automatisch in den entsprechenden Typ gecastet. Wollen Sie in XAML einer ment-Syntax bildet eine Ausnahme: Bei ihr wird das Property-Element einer .NET-Property Property keinen primitiven Typ und keinen Aufzählungswert, sondern ein »richtiges« Ob- und nicht einer Klasse zugeordnet. jekt zuweisen, ist dies mit der Attribut-Syntax nicht ohne Weiteres möglich. Verwenden Sie stattdessen die Property-Element-Syntax. Hinweis Hinweis Auf einem Property-Element können Sie keine XML-Attribute setzen. XML-Attribute verwei- sen in XAML immer auf Properties oder Events eines Objekts. Ein Property-Element definiert Um ein Objekt mit der Attribut-Syntax zuzuweisen, gibt es einerseits noch die Möglichkeit allerdings kein Objekt, sondern lediglich eine Property. Folglich kann ein Property-Element der (später beschriebenen) Markup-Extensions und andererseits die Type-Converter. Type- keine XML-Attribute besitzen. Converter konvertieren den im XML-Attribut angegebenen String in das von der Property be- nötigte Objekt. Dadurch können Sie beispielsweise der Background-Property eines Button- Elements mit der Attribut-Syntax den String Blue zuweisen. Im Hintergrund erstellt ein Type- Die Property-Element-Syntax erlaubt es, einer Property ein komplexes Objekt zuzuweisen Converter automatisch einen SolidColorBrush, der der Background-Property des Button- und nicht nur primitive Typen oder Aufzählungswerte. Folgende Loose-XAML-Datei weist Objekts zugewiesen wird. Der Button wird somit blau dargestellt. unter Verwendung der Property-Element-Syntax der Content-Property eines Buttons ein Image-Objekt und der Background-Property einen LinearGradientBrush zu:
Ein Property-Element besteht aus dem Namen der Klasse und der eigentlichen Property. Klassenname und Property sind durch einen Punkt getrennt. Das allgemeingültige Format der Property-Element-Syntax lautet demzufolge
Abbildung 3.2 Ein Button, dessen Content-Property ein Image und dessen Background-Property einen LinearGradientBrush enthält
156 157 7201.book Seite 158 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 159 Donnerstag, 5. September 2019 8:43 08
3XAML 3.4 Properties in XAML setzen
3.4.3 Die Content-Property (Default-Property) Die Content-Property der Klasse Button heißt Content, also so wie die Content-Property der Klasse Window. Das ist nicht verwunderlich, denn beide Klassen erben diese Property von Con- Um die Darstellung von XAML etwas kompakter zu machen, definieren viele Klassen der tentControl. Auf der Klasse ContentControl ist auch das ContentProperty-Attribut mit der WPF eine Property, die in XAML per Default gesetzt wird, wenn sich etwas direkt innerhalb Property Content definiert. Den Button aus Listing 3.8 könnten Sie somit auch so wie in Lis- 3 eines Objektelements befindet und nicht explizit über die Property-Element-Syntax einer ting 3.10 mit zwei Zeilen weniger erstellen (verzichten Sie dazu auf die Property-Elemente Property zugeordnet ist. Die TextBox-Klasse definiert die Text-Property als Default-Property.
Listing 3.9 Beispiele\K03\07 ContentProperty\MainWindow.xaml 3.4.4 Die Attached-Property-Syntax
Die per Default gesetzte Property wird als Content-Property bezeichnet. Zum Festlegen der Für die Attached Properties, eine spezielle Implementierung der in Kapitel 7 beschriebenen Content-Property wird auf Klassenebene das Attribut ContentPropertyAttribute (Name- Dependency Properties, besitzt XAML eine eigene Syntax. Das Besondere an Attached Prop- space: System.Windows.Markup) deklariert, dessen Konstruktor einen string mit dem Namen erties ist, dass sie in einer Klasse definiert, aber auf Objekten anderer Klassen gespeichert der gewünschten Default-Property entgegennimmt. Die Klasse TextBox setzt die Text-Prop- werden. erty als Content-Property: Diese Möglichkeit wird insbesondere bei Layout-Panels genutzt. In Listing 3.11 werden die [ContentProperty("Text")] Attached Properties Left und Top der Canvas-Klasse verwendet, um einen Button in einem public class TextBox:TextBoxBase,... Canvas absolut anzuordnen: auf der TextBox-Klasse nach dem Attribut ContentProperty, findet im ContentProperty-Attri- but die Text-Property und weist den nicht in einem Property-Element angegebenen Wert in- Listing 3.11 Beispiele\K03\09 AttachedProperties\MainWindow.xaml nerhalb des TextBox-Elements der Text-Property zu. Die C#-Variante des XAML-Ausschnitts aus Listing 3.11 benötigt etwas mehr Code (siehe Lis- Von der Content-Property der Klassen Window und auch ListBox wurde in diesem Kapitel be- ting 3.12): reits implizit Gebrauch gemacht. Die Content-Property von Window heißt – rein zufälliger- weise – Content, die der Klasse ListBox heißt Items. Ohne die Content-Property müssten Sie var c = new Canvas(); zum Zuweisen von Objekten fast immer die Property-Element-Syntax verwenden, wodurch c.Width = 300; Ihre XAML-Dokumente bestimmt einige Zeilen größer wären. c.Height = 300;
158 159 7201.book Seite 160 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 161 Donnerstag, 5. September 2019 8:43 08
3XAML 3.5 Type-Converter
var b = new Button(); ̈ Type-Converter in C# verwenden – Natürlich lassen sich Type-Converter auch in C# ver- b.Content = "OK"; wenden. Dieser Abschnitt zeigt, wie’s geht. Canvas.SetLeft(b, 10); Canvas.SetTop(b, 40); 3 c.Children.Add(b); 3.5.1 Vordefinierte Type-Converter Die Button-Klasse erbt von der Klasse FrameworkElement die Property Margin. Die Margin-Prop- Listing 3.12 C#-Variante zu Listing 3.11 erty gibt den Rand eines FrameworkElements an und ist vom Typ Thickness (Namespace: Sys- In Kapitel 6, »Layout«, werden Sie die Attached-Property-Syntax intensiv einsetzen. In Kapi- tem.Windows). tel 7, »Dependency Properties«, erfahren Sie, wie Sie eigene Attached Properties implemen- In XAML setzen Sie die Margin-Property eines Buttons wie folgt: tieren.
Listing 3.13 Beispiele\K03\10 ThicknessTypeConverter\MainWindow.xaml 3.5 Type-Converter Die C#-Variante zur Erstellung eines gleichen Button-Objekts sehen Sie in Listing 3.14: XAML-Dokumente sind oft weitaus kompakter als C#-Code. Ein Grund dafür ist unter ande- var button = new Button rem die Verwendung von Type-Convertern. Wird ein XAML-Dokument geparst, werden die { mit der Attribut-Syntax angegebenen Strings für Properties mit primitiven Typen oder Auf- Margin = new Thickness(10), zählungen automatisch gecastet. Für Objekte anderer Typen ist die Verwendung der Proper- Content = "OK" ty-Element-Syntax notwendig, es sei denn, für den Typ existiert ein Type-Converter oder Sie }; verwenden eine Markup-Extension. Letztere stelle ich Ihnen im nächsten Abschnitt vor. Listing 3.14 Beispiele\K03\10 ThicknessTypeConverter\MainWindow.xaml.cs Type-Converter konvertieren den in einem XML-Attribut angegebenen String in das Objekt, das die dahinterliegende .NET-Property benötigt. Anstelle der Property-Element-Syntax ist Der String 10 wird in XAML demnach automatisch in ein Thickness-Objekt konvertiert. Wie es somit möglich, ein Objekt direkt mit der Attribut-Syntax einer Property zuzuweisen. ist dies möglich? Zur Klasse Thickness existiert eine Klasse ThicknessConverter, die aus einem Ein Type-Converter ist ein Objekt der Klasse TypeConverter (Namespace: System.Component- String ein Thickness-Objekt erzeugen kann. Die Verbindung der Thickness-Klasse zur Klasse Model) beziehungsweise einer Subklasse. Die Klasse TypeConverter existiert bereits seit .NET ThicknessConverter ist über das TypeConverterAttribute definiert, das auf der Klasse Thick- 1.0 und enthält unter anderem die virtuelle Methode ConvertFrom, die sich in Subklassen ness gesetzt ist. Mehr zum TypeConverterAttribute lesen Sie im nächsten Abschnitt. Die überschreiben lässt. Die ConvertFrom-Methode gibt den konvertierten Wert zurück. XAML-Syntax zum Setzen der Margin-Property müsste ohne einen Type-Converter wie folgt In XAML wandelt ein Type-Converter den mittels Attribut-Syntax angegebenen String in aussehen: den Typ der Property um. XAML-Code wirkt dadurch weitaus kompakter als C#-Code, da die wodurch XAML kompakt erscheint. ̈ eigene Type-Converter implementieren – Um die Funktionsweise von Type-Convertern Listing 3.15 Beispiele\K03\10 ThicknessTypeConverter\MainWindow.xaml zu verstehen, implementieren wir einen eigenen Type-Converter.
160 161 7201.book Seite 162 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 163 Donnerstag, 5. September 2019 8:43 08
3XAML 3.5 Type-Converter
Das Erzeugen des Thickness-Objekts in Listing 3.15 ist allerdings auch nur möglich, da für alle der Definition der Properties Name und Address die ToString-Methode überschrieben. Da- primitiven Typen und Aufzählungen standardmäßig bereits Type-Converter existieren. Nur durch lassen sich in XAML erstellte Friend-Objekte in einem Window-Objekt anzeigen. dadurch können die Strings 10 in double-Werte umgewandelt und den Properties Bottom, public class Friend Left, Right und Top des Thickness-Objekts zugewiesen werden. 3 { Type-Converter erhöhen also nicht nur die Lesbarkeit von XAML, indem sie weitaus kom- public string Name { get; set; } pakteren Code ermöglichen, sondern sind auch die Grundlage, um in XAML überhaupt Ob- public Address Address { get; set; } jekte mit primitiven Typen und Aufzählungen erstellen zu können. public override string ToString() { if (Address != null) Achtung return string.Format("Name: {0}\nAdresse: {1} {2} {3} {4}" Die Type-Converter greifen nur, wenn die Property auch tatsächlich von dem entsprechen- ,Name den Typ ist. Wollen Sie einer Property vom Typ der Aufzählung Visibility einen Wert zuwei- , Address.Street sen, genügt es, diesen Wert als String anzugeben. Wollen Sie einer Property vom Typ object , Address.StreetNumber einen Wert der Aufzählung Visibility zuweisen, müssen Sie den Wert explizit mit der , Address.ZipCode x:Static-Markup-Extension aus der Visibility-Aufzählung holen, damit er nicht als String , Address.City); interpretiert wird: return Name; ... PropertyVomTypObject="{x:Static Visibility.Visible}" ... } } Die WPF besitzt viele vordefinierte Type-Converter. Beispielsweise gibt es Type-Converter Listing 3.17 Beispiele\K03\11 SimpleTypeConverter\Friend.cs für die Klassen Brush oder Color, die Sie in Kapitel 13, »2D-Grafik«, kennenlernen werden.
In Listing 3.18 wird in XAML innerhalb eines Window-Objekts ein Friend-Objekt mit einer 3.5.2 Eigene Type-Converter implementieren Adresse erzeugt. Zum Setzen der Address-Property muss die Property-Element-Syntax ver- wendet werden. Im Folgenden werden Sie anhand eines kleinen Beispiels lernen, wie Sie einen eigenen Type- Converter implementieren. Dazu erstellen wir zunächst eine Klasse Address, die die Proper-
162 163 7201.book Seite 164 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 165 Donnerstag, 5. September 2019 8:43 08
3XAML 3.5 Type-Converter
return base.ConvertFrom(context, culture, value); } ... } 3
Listing 3.20 Beispiele\K03\11 SimpleTypeConverter\AddressConverter.cs
Ist in der überschriebenen ConvertFrom-Methode der in der Parametervariablen value enthal- tene Wert ein string, wird dieser nach Leerzeichen gesplittet. Aus dem daraus erhaltenen Abbildung 3.3 Der Rückgabewert der ToString-Methode eines Friend-Objekts String-Array wird ein Address-Objekt erzeugt, das als Rückgabewert der ConvertFrom-Metho- de zurückgegeben wird. Während in Listing 3.18 das Property-Element
public class AddressConverter : TypeConverter Listing 3.21 Beispiele\K03\11 SimpleTypeConverter\Address.cs { public override object ConvertFrom(ITypeDescriptorContext Mit dem Code in Listing 3.21 ist die Verbindung zwischen der Address-Klasse und der Address- context,System.Globalization.CultureInfo culture,object value) Converter-Klasse hergestellt. Wird das XAML-Dokument deserialisiert, ruft der XAML-Parser { für eine mittels Attribut-Syntax gesetzte Address-Property – wie in Listing 3.19 zu sehen ist – if (value is string) die ConvertFrom-Methode der AddressConverter-Klasse auf. Er erhält als Rückgabewert der { ConvertFrom-Methode das von der Address-Property verlangte Address-Objekt. string[] array = value.ToString().Split(' '); Mit der erstellten AddressConverter-Klasse stehen Ihnen jetzt drei Möglichkeiten offen, um if (array.Length == 4) in XAML ein Friend-Objekt mit einer Adresse zu erzeugen (siehe Listing 3.22): { return new Address {
164 165 7201.book Seite 166 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 167 Donnerstag, 5. September 2019 8:43 08
3XAML 3.5 Type-Converter
Der XAML-Parser sucht in diesem Fall den zur Klasse gehörenden Type-Converter, um aus
166 167 7201.book Seite 168 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 169 Donnerstag, 5. September 2019 8:43 08
3XAML 3.6 Markup-Extensions
3.6 Markup-Extensions Tipp Mit der Attribut-Syntax lassen sich einer Property nur primitive Typen und Aufzählungs- In Kapitel 2, »Das Programmiermodell«, wurde beschrieben, dass unter anderem die Width- und Height-Properties – beide sind vom Typ double – der Klasse FrameworkElement in logi- werte zuweisen. Mit den Type-Convertern haben Sie eine Möglichkeit gesehen, auch Proper- 3 schen Einheiten angegeben werden (was 1/96 Inch entspricht). In XAML lassen sich dank ties mit komplexeren Typen über die Attribut-Syntax zu initialisieren. Die Markup-Exten- Type-Convertern für Width und Height und auch für andere Properties, die logische Einheiten sions verschaffen Ihnen eine weitere Möglichkeit, Objekte über die Attribut-Syntax und über verlangen, sogenannte »qualifizierte« double-Werte angeben, beispielsweise wie folgt: die Property-Element-Syntax zu erstellen und einer Property zuzuweisen. Markup-Exten- sions bieten Ihnen zudem die Option, nicht unbedingt ein neues Objekt erstellen zu müssen, sondern beispielsweise mit einem Data Binding ein bereits existierendes Objekt zu referen- Der Button wird jetzt 10 cm breit dargestellt. Sie haben folgende Werte, um einen double zu zieren. Eine Markup-Extension verweist aus XAML auf eine Klasse, die von der abstrakten qualifizieren: Klasse MarkupExtension (Namespace: System.Windows.Markup) abgeleitet ist und deren Metho- ̈ px – der Default; wird verwendet, wenn Sie nichts angeben. px sind logische Einheiten de ProvideValue implementiert. (1/96 Inch) und nicht, wie die Bezeichnung vermuten lässt, Pixel. Im Folgenden sehen wir uns drei Bereiche an: ̈ in – Angabe von Inches; 1 in = 96 px ̈ ̈ cm – Angabe von Zentimetern; 1cm = 96 ÷ 2,54 px. Der oben gezeigte Button ist also nach Verwenden von Markup-Extensions in XAML und C# – Dieser Abschnitt zeigt, was es mit dieser Formel 10 × 96 ÷ 254 px breit, was gerundet 378 px (logischen Einheiten) ent- Markup-Extensions auf sich hat. spricht. ̈ XAML Markup-Extensions – Dieser Abschnitt gibt Ihnen einen Überblick über die Mark- ̈ pt – Angabe in Points; 1 pt = 96 ÷ 72 px. Die Einheit Points ist eine allgemeine Einheit zur up-Extensions, die im XML-Namespace von XAML und somit im CLR-Namespace Sys- Angabe von Schriftgrößen. Ein Point entspricht dabei exakt 1/72 Inch. Damit entspricht tem.Windows. Markup definiert sind. eine logische Einheit 0,75 Points (= 96 ÷ 72). Eine Angabe von 36 Point ist also genau ein ̈ Markup-Extensions der WPF – Der dritte Abschnitt gibt Ihnen eine Übersicht über die halber Inch. Markup-Extensions, die in den CLR-Namespaces der WPF definiert sind. Das Qualifizieren eines doubles mit einem der oben dargestellten Werte funktioniert nur, da die Width- und Height-Properties von FrameworkElement – und auch viele andere Properties – 3.6.1 Verwenden von Markup-Extensions in XAML und C# mit einem TypeConverterAttribute ausgestattet sind. Das TypeConverterAttribute kann nicht nur auf Klassenebene, sondern auf allen Mitgliedern einer Klasse stehen, da das Attri- Wie bereits erwähnt wurde, sind Markup-Extensions Klassen, die von der abstrakten Klasse but selbst mit AttributeTargets.All definiert ist. Die in FrameworkElement definierte Width- MarkupExtension (Namespace: System.Windows.Markup) abgeleitet sind und deren Methode Property hat die folgende Signatur: ProvideValue implementieren. Markup-Extensions werden beim Verwenden der Attribut- [TypeConverter(typeof(LengthConverter)),...] Syntax in geschweifte Klammern eingeschlossen. Der Ausschnitt in Listing 3.24 nutzt Mark- public double Width up-Extensions mit der Attribut-Syntax: {...}
Static, Null und Binding verweisen auf Klassen, die von der Klasse MarkupExtension abgeleitet sind. Die Klassen heißen dabei StaticExtension, NullExtension und Binding. Der XAML-Par-
168 169 7201.book Seite 170 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 171 Donnerstag, 5. September 2019 8:43 08
3XAML 3.6 Markup-Extensions
ser sucht automatisch in den entsprechenden .NET-Namespaces nach Klassen, die dem ers- Den Button aus Listing 3.24 erzeugen Sie in C# wie folgt: ten Wort in den geschweiften Klammern entsprechen. Dabei hängt der XAML-Parser auto- var btn = new System.Windows.Controls.Button(); matisch ein »Extension« an den Klassennamen an, wenn er die entsprechende Klasse nicht btn.Height = System.Windows.SystemParameters.CaptionHeight; findet und der Klassenname noch kein Extension-Suffix besitzt. Von den Klassen wird eine 3 btn.Background = null; Instanz erzeugt. Das in Listing 3.24 erzeugte Binding-Objekt setzt die Properties ElementName var b = new System.Windows.Data.Binding(); und Path. b.ElementName = "slider"; b.Path = new System.Windows.PropertyPath("Value"); Hinweis btn.SetBinding(System.Windows.Controls.Button.ContentProperty, b); Beachten Sie, dass für die gesetzten Properties einer Markup-Extension bei der Attribut-Syn- Listing 3.25 Der Button aus Listing 3.24 in C# tax keinerlei Anführungszeichen oder Hochkommas verwendet werden. Stattdessen wird der Wert für eine Eigenschaft direkt hinter das Gleichheitszeichen gesetzt. Einzelne Proper- Anstatt Markup-Extensions in XAML mithilfe der geschweiften Klammern und der Attribut- ties werden mit einem Komma voneinander getrennt: Syntax zu verwenden, können Sie Markup-Extensions auch als gewöhnliche Objektelemente "{Binding ElementName=slider,Path=Value}" erstellen. Listing 3.26 ist analog zu Listing 3.24, allerdings werden die Markup-Extensions nicht mit der Attribut-Syntax zugewiesen, sondern jetzt als Objektelemente erstellt: Abbildung 3.4 zeigt das Fenster mit dem XAML-Inhalt aus Listing 3.24.
Folgende Zeile weist der Content-Property eines Buttons den String {OK} zu: Listing 3.26 Beispiele\K03\13 MarkupExtensionsObjectElementSyntax\MainWindow.xaml Ohne das leere Klammerpaar vor {OK} würde der XAML-Parser nach einer Klasse OK suchen, Wie Listing 3.26 zeigt, sind die Markup-Extensions Static und Null im XAML-Namespace de- nicht fündig werden und folglich eine Exception auslösen. Nur bei der Attribut-Syntax inter- finiert, die Markup-Extension Binding dagegen im XML-Namespace der WPF. pretiert der XAML-Parser ein geschweiftes Klammernpaar als Markup-Extension. Einen But- ton mit dem Text {OK} könnten Sie somit auch wie folgt erstellen:
170 171 7201.book Seite 172 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 173 Donnerstag, 5. September 2019 8:43 08
3XAML 3.6 Markup-Extensions
3.6.2 XAML-Markup-Extensions Markup-Extension Beschreibung Tabelle 3.1 zeigt die Markup-Extensions von XAML, wobei angenommen wird, dass der XML- x:Static Im folgenden Beispiel wurde der System-Namespace dem XML- Namespace von XAML wie üblich über ein x-Alias verfügt. (Forts.) Namespace mit dem Präfix sys zugeordnet. Der Inhalt eines But- 3 tons wird auf den Wert der statischen Property MaxValue der Markup-Extension Beschreibung Klasse System. Int32 gesetzt. x:Array Nutzen Sie die x:Array-Markup-Extension, um in XAML ein .NET-
948 949 7201.book Seite 950 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 951 Donnerstag, 5. September 2019 8:43 08
15 Animationen 15.3 Basis-Animationen in XAML
15.3.2 Das Storyboard als Timeline-Container Bisher wurde zur Children-Property des Storyboards nur eine Timeline bzw. eine DoubleAni- mation hinzugefügt. Mit mehreren Timelines lassen sich komplexere Animationen erstellen.
950 951 7201.book Seite 952 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 953 Donnerstag, 5. September 2019 8:43 08
15 Animationen 15.3 Basis-Animationen in XAML
Nachdem Sie das Storyboard und all die Kinder initialisiert haben, stellt sich die Frage, wie ̈ PauseStoryboard Sie die Animation beziehungsweise das Storyboard starten. Die BeginAnimation-Methode ̈ RemoveStoryboard nimmt eine AnimationTimeline entgegen, aber Storyboard ist keine solche. AnimationTimeline ̈ ResumeStoryboard und Storyboard sind lediglich beide vom Typ Timeline. Dabei definiert AnimationTimeline die ̈ SeekStoryboard eigentliche Animation für eine bestimmte Property eines bestimmten Objekts. Das Story- ̈ board ist »nur« ein Container für mehrere Timelines. SetStoryboardSpeedRatio ̈ SkipStoryboardToFill Die Klasse Storyboard besitzt Methoden wie Begin, Pause und Stop. Rufen Sie die Begin- Methode auf, um das Storyboard zu starten. Dabei geben Sie im einfachsten Fall ein Frame- ̈ StopStoryboard workElement mit, das sich im selben NameScope befinden muss wie die Zielobjekte der im Sto- Damit das Ganze funktioniert, setzen Sie lediglich die Name-Property Ihres BeginStoryboard- ryboard enthaltenen Animationen. Hat eine Animation im Storyboard kein Zielobjekt ge- Elements. Die abstrakte Klasse ControllableStoryboardAction besitzt die Property BeginSto- setzt, wird das an die Begin-Methode übergebene Objekt als Zielobjekt verwendet. Nach dem ryboardName (Typ String). Diese Property setzen Sie beispielsweise auf einem PauseStory- Aufruf von Begin startet das Storyboard. Im Fall von Listing 15.9 ist das Grid das Zielobjekt: board-Element auf den String, den Sie auch in der Name-Property des BeginStoryboard-Ele- sb.Begin(grid); ments angegeben haben. Schon ist die Verbindung zwischen BeginStoryboard und den ControllableStoryboards geschaffen, und Animationen lassen sich auch rein in XAML mit Triggern steuern. Tipp Die Klassen FrameworkElement und FrameworkContentElement besitzen beide mehrere Über- Listing 15.10 enthält wieder die bereits im C#-Abschnitt verwendete Fußball-Animation (sie- ladungen einer Methode namens BeginStoryboard. Diese nimmt im einfachsten Fall ein he Abbildung 15.11). Das Grid in Listing 15.10 enthält mehrere Trigger, die auf das Routed Storyboard entgegen und kapselt lediglich den oben dargestellten Aufruf der Begin-Metho- Event Button.Click reagieren. Je nach geklicktem Button wird die entsprechende Controll- 15 de eines Storyboards. Statt ableTriggerAction ausgeführt.
sb.Begin(grid);
952 953 7201.book Seite 954 Donnerstag, 5. September 2019 8:43 08
15 Animationen
Listing 15.10 Beispiele\K15\08 AnimationKontrollierenInXAML\MainWindow.xaml
Abbildung 15.11 Gesteuerte Animation eines Fußballs – rein in XAML
954 7201.book Seite 3 Donnerstag, 5. September 2019 8:43 08
Auf einen Blick
Auf einen Blick
TEIL I WPF-Grundlagen und -Konzepte 1 Einführung in die WPF ...... 43 2 Das Programmiermodell ...... 77 3 XAML ...... 143 4 Der Logical und der Visual Tree ...... 193 5 Controls ...... 243 6 Layout ...... 323 7 Dependency Properties ...... 403 8 Routed Events ...... 445 9 Commands ...... 487
TEIL II Fortgeschrittene Techniken 10 Ressourcen ...... 535 11 Styles, Trigger und Templates ...... 573 12 Daten ...... 647
TEIL III Reichhaltige Medien und eigene Controls 13 2D-Grafik ...... 791 14 3D-Grafik ...... 869 15 Animationen ...... 915 16 Audio und Video ...... 981 17 Eigene Controls ...... 1003 18 Text und Dokumente ...... 1059
TEIL IV Interoperabilität und Apps 19 Standard-Dialoge, Windows Taskbar und mehr ...... 1123 20 Interoperabilität ...... 1143 21 Universal Windows Apps und WinUI ...... 1177 7201.book Seite 5 Donnerstag, 5. September 2019 8:43 08
Inhalt
Inhalt
Materialien zum Buch ...... 25 Vorwort ...... 27 Hinweise zum Buch ...... 31
TEIL I WPF-Grundlagen und -Konzepte
1 Einführung in die WPF 43
1.1 Die WPF und .NET ...... 43 1.1.1 .NET Core 3.0 und .NET Framework 4.8 ...... 43 1.1.2 Die WPF und Visual Studio 2019 ...... 45 1.1.3 Die WPF als zukünftiges Programmiermodell ...... 45 1.1.4 Stärken und Eigenschaften der WPF ...... 47 1.1.5 Auf Wiedersehen, GDI+ ...... 50 1.2 Von Windows 1.0 zur Windows Presentation Foundation ...... 50 1.2.1 Die ersten Wrapper um die Windows-API ...... 51 1.2.2 Windows Forms und GDI+ ...... 51 1.2.3 Die Windows Presentation Foundation ...... 52 1.3 Die Architektur der WPF ...... 53 1.3.1 MilCore – die »Display Engine« ...... 55 1.3.2 WindowsBase ...... 57 1.3.3 PresentationCore ...... 57 1.3.4 PresentationFramework ...... 58 1.3.5 Vorteile und Stärken der WPF-Architektur ...... 58 1.4 Konzepte ...... 59 1.4.1 XAML ...... 60 1.4.2 Dependency Properties ...... 62 1.4.3 Routed Events ...... 65 1.4.4 Commands ...... 69 1.4.5 Styles und Templates ...... 71 1.4.6 3D ...... 73 1.5 Zusammenfassung ...... 74
5 7201.book Seite 6 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 7 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
2 Das Programmiermodell 77 2.4 Application, Dispatcher und Window ...... 109 2.4.1 Die Klasse »Application« ...... 110 2.1 Grundlagen der WPF ...... 78 2.4.2 Übersicht der Application-Events ...... 111 2.1.1 Namespaces ...... 78 2.4.3 Events der Application-Klasse verwenden ...... 111 2.1.2 Assemblies ...... 79 2.4.4 Die Properties »Windows« und »MainWindow« ...... 114 2.1.3 Die Klassenhierarchie ...... 79 2.4.5 Das Shutdown-Verhalten Ihrer Applikation ...... 115 2.1.4 Object ...... 80 2.4.6 Die Klasse »Dispatcher« ...... 117 2.1.5 DispatcherObject ...... 80 2.4.7 Fenster mit der Klasse »Window« ...... 124 2.1.6 DependencyObject ...... 82 2.4.8 Methoden der Klasse »Window« ...... 124 2.1.7 Visual ...... 82 2.4.9 Die Komponenten eines Fensters ...... 125 2.1.8 UIElement ...... 82 2.4.10 Übersicht der Properties der Klasse »Window« ...... 127 2.1.9 FrameworkElement ...... 83 2.4.11 Dialogspezifische Properties ...... 133 2.1.10 Control ...... 84 2.4.12 Modale Dialoge ...... 133 2.1.11 ContentElement ...... 85 2.4.13 Nicht-modale Dialoge ...... 137 2.1.12 FrameworkContentElement ...... 85 2.4.14 Events der Klasse »Window« ...... 138 2.1.13 Freezable ...... 85 2.5 Zusammenfassung ...... 139 2.1.14 Visual3D ...... 86 2.1.15 UIElement3D ...... 87 2.2 Projektvorlagen in Visual Studio 2019 ...... 87 3XAML 143 2.2.1 WPF-App ...... 88 2.2.2 WPF-Browser-App (Web) ...... 89 3.1
6 7 7201.book Seite 8 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 9 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
3.6 Markup-Extensions ...... 169 5 Controls 243 3.6.1 Verwenden von Markup-Extensions in XAML und C# ...... 169 3.6.2 XAML-Markup-Extensions ...... 172 5.1 Die Klasse »Control« ...... 246 3.6.3 Markup-Extensions der WPF ...... 173 5.2 ContentControls ...... 248 3.7 XAML-Spracherweiterungen ...... 175 5.2.1 Buttons ...... 251 3.8 Collections in XAML ...... 181 5.2.2 Der »normale« Button ...... 251 3.8.1 Collections, die IList implementieren ...... 181 5.2.3 Der RepeatButton ...... 253 3.8.2 Collections, die IDictionary implementieren ...... 183 5.2.4 Der ToggleButton ...... 254 5.2.5 Der RadioButton ...... 255 3.9 XamlReader und XamlWriter ...... 185 5.2.6 Die CheckBox ...... 257 3.9.1 XAML mit XamlReader dynamisch laden ...... 186 5.2.7 Labels ...... 258 3.9.2 Objekte mit XamlWriter in XAML serialisieren ...... 188 5.2.8 ToolTips anzeigen ...... 260 3.10 Zusammenfassung ...... 189 5.2.9 Die Klasse »ToolTip« ...... 261 5.2.10 Die Klasse »ToolTipService« ...... 263 5.2.11 Scrollen mit ScrollViewer ...... 264 5.2.12 WPF- und HTML-Inhalte mit Frame darstellen ...... 266 4 Der Logical und der Visual Tree 193 5.2.13 ContentControls mit Header ...... 268 5.2.14 Inhalte mit dem Expander auf- und zuklappen ...... 268 4.1 Zur Veranschaulichung verwendete Komponenten ...... 196 5.2.15 Inhalte mit der GroupBox gruppieren ...... 270 4.1.1 Der InfoDialog von FriendStorage ...... 196 5.2.16 TabItems für ein TabControl ...... 270 4.1.2 Die Anwendung »XAMLPadExtensionClone« ...... 197 5.3 ItemsControls ...... 271 4.2 Der Logical Tree ...... 199 5.3.1 ItemsControls mit Header ...... 274 4.2.1 Der Logical Tree des InfoDialogs ...... 199 5.3.2 Navigation mit einer ToolBar ...... 274 4.2.2 Für den Logical Tree verantwortliche Klassen ...... 203 5.3.3 TreeViewItem und MenuItem ...... 278 4.2.3 Die Klasse LogicalTreeHelper ...... 207 5.3.4 Baumansicht mit der TreeView ...... 278 4.2.4 NameScopes, FindName und FindLogicalNode ...... 212 5.3.5 Navigation über Menüs ...... 282 4.2.5 NameScopes – die Namensbereiche ...... 212 5.3.6 Das gewöhnliche Menü ...... 283 4.2.6 INameScope, FrameworkElement und FrameworkContentElement ...... 216 5.3.7 Das Kontextmenü ...... 285 4.2.7 Die Methode »LogicalTreeHelper.FindLogicalNode« ...... 218 5.3.8 Elemente mit einem Selector auswählen ...... 287 4.3 Der Visual Tree ...... 220 5.3.9 Listen mit der ComboBox anzeigen ...... 288 4.3.1 Der Visual Tree des InfoDialogs ...... 220 5.3.10 Eine Liste in der ListBox anzeigen ...... 291 4.3.2 Eigene Klassen im Visual Tree ...... 223 5.3.11 Die ListView als erweiterte ListBox ...... 292 4.3.3 Die Klasse »VisualTreeHelper« ...... 227 5.3.12 Mehrere Tabs mit einem TabControl ...... 295 4.3.4 Der Visual Tree und das Rendering ...... 230 5.3.13 Das Ribbon ...... 295 4.4 Der Live Visual Tree in Visual Studio 2019 ...... 235 5.3.14 Eine StatusBar mit Informationen ...... 300 4.4.1 Den Live Visual Tree beim Debuggen anzeigen ...... 236 5.3.15 »Alternating Rows« mit AlternationCount ...... 300 4.4.2 Elemente in der Anwendung auswählen ...... 237 5.4 Controls zur Textdarstellung und -bearbeitung ...... 302 4.4.3 Eigenschaften zur Laufzeit ansehen und anpassen ...... 239 5.4.1 »TextBox« zum Editieren von Text ...... 302 4.5 Zusammenfassung ...... 240 5.4.2 RichTextBox für formatierten Text ...... 304 5.4.3 PasswordBox für maskierten Text ...... 304
8 9 7201.book Seite 10 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 11 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
5.4.4 TextBlock zur Anzeige von Text ...... 305 6.2.11 »LayoutTransform« vs. »RenderTransform« ...... 343 5.4.5 Zeichnen mit dem InkCanvas ...... 305 6.2.12 »RotateTransform« ...... 346 5.5 Datum-Controls ...... 307 6.2.13 »ScaleTransform« ...... 347 6.2.14 »SkewTransform« ...... 349 5.5.1 Calendar ...... 307 6.2.15 »TranslateTransform« ...... 349 5.5.2 DatePicker ...... 310 6.2.16 »MatrixTransform« ...... 350 5.6 Range-Controls ...... 312 6.2.17 »TransformGroup« ...... 352 5.6.1 Bereich mit Slider auswählen ...... 313 6.3 Panels ...... 354 5.6.2 ProgressBar zur Statusanzeige ...... 314 6.3.1 Die Klasse »Panel« ...... 354 5.6.3 Scrollen mit der ScrollBar ...... 314 6.3.2 Canvas ...... 355 5.7 Sonstige, einfachere Controls ...... 315 6.3.3 StackPanel ...... 358 5.7.1 Decorator zum Ausschmücken ...... 315 6.3.4 WrapPanel ...... 360 5.7.2 Einfacher Rahmen mit der Border-Klasse ...... 315 6.3.5 DockPanel ...... 361 5.7.3 Elemente mit der Viewbox skalieren ...... 316 6.3.6 Grid ...... 363 5.7.4 Bilder mit der Image-Klasse darstellen ...... 317 6.3.7 Die Höhe von Zeilen und die Breite von Spalten ...... 365 5.7.5 Einfaches Popup anzeigen ...... 318 6.3.8 GridSplitter ...... 368 5.8 Zusammenfassung ...... 321 6.3.9 Geteilte Größen – »SharedSizeGroup« ...... 372 6.3.10 Das Grid als Alleskönner ...... 375 6.3.11 Primitive Panels ...... 377 6.3.12 »UniformGrid« ...... 377 323 6Layout 6.3.13 »VirtualizingPanels« ...... 378 6.3.14 TabPanel ...... 380 6.1 Der Layoutprozess ...... 323 6.3.15 ToolBarOverflowPanel ...... 380 6.1.1 Die zwei Schritte des Layoutprozesses ...... 324 6.3.16 Übersicht der Alignments in den verschiedenen Panels ...... 380 6.1.2 Schritt 1: Measure ...... 324 6.3.17 Wenn der Platz im Panel nicht ausreicht ...... 383 6.1.3 Schritt 2: Arrange ...... 325 6.4 Das Layout von FriendStorage ...... 385 6.1.4 Fazit aus den beiden Schritten ...... 325 6.4.1 Das Hauptfenster aus Benutzersicht ...... 385 6.1.5 »MeasureOverride« und »ArrangeOverride« ...... 326 6.4.2 Das Hauptfenster aus Entwicklersicht ...... 387 6.1.6 Ein eigenes Layout-Panel (DiagonalPanel) ...... 327 6.4.3 Animation des Freunde-Explorers ...... 396 6.1.7 Zusammenfassung des Layoutprozesses ...... 332 6.5 Zusammenfassung ...... 401 6.2 Layoutfunktionalität von Elementen ...... 333 6.2.1 Width und Height ...... 333 6.2.2 Margin und Padding ...... 334 6.2.3 Margin ...... 334 7 Dependency Properties 403 6.2.4 Padding ...... 336 6.2.5 Alignments ...... 337 7.1 Die Keyplayer ...... 404 6.2.6 »HorizontalAlignment« und »VerticalAlignment« ...... 337 7.1.1 »DependencyObject« und »DependencyProperty« ...... 404 6.2.7 »HorizontalContentAlignment« und »VerticalContentAlignment« ...... 338 7.1.2 Was ist die Property Engine? ...... 406 6.2.8 Die Visibility-Property ...... 339 7.2 Dependency Properties ...... 406 6.2.9 Die UseLayoutRounding-Property ...... 339 7.2.1 Eine Dependency Property implementieren ...... 408 6.2.10 Transformationen ...... 341
10 11 7201.book Seite 12 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 13 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
7.2.2 Klassische FontSize-Property ...... 408 8.4 Routed Events der WPF ...... 471 7.2.3 »FontSize« als Dependency Property ...... 408 8.4.1 Tastatur-Events ...... 473 7.2.4 Metadaten einer Dependency Property ...... 411 8.4.2 Maus-Events ...... 476 7.2.5 Die Callback-Methoden der Metadaten ...... 415 8.4.3 Mouse-Capturing ...... 478 7.2.6 Metadaten in Subklassen überschreiben ...... 416 8.4.4 Stylus-Events (Stift) ...... 480 7.2.7 Default-Metadaten ...... 417 8.4.5 Multitouch-Events ...... 481 7.2.8 Validieren einer Dependency Property ...... 417 8.4.6 Die statischen Mitglieder eines FrameworkElements ...... 484 7.2.9 Die FontSize-Property als Ziel eines Data Bindings ...... 420 8.5 Zusammenfassung ...... 485 7.2.10 Existierende Dependency Properties verwenden ...... 422 7.2.11 Read-only-Dependency-Properties implementieren ...... 425 7.2.12 Den Wert einer Dependency Property ermitteln ...... 427 7.2.13 Lokal gesetzte Werte löschen ...... 429 9 Commands 487 7.2.14 Überblick über die Quellen mit »DependencyPropertyHelper« ...... 430 7.2.15 Auf Änderungen in existierenden Klassen lauschen ...... 430 9.1 Die Keyplayer ...... 488 7.3 Attached Properties ...... 431 9.1.1 Das Interface »ICommand« ...... 488 7.3.1 Eine Attached Property implementieren ...... 432 9.1.2 Das Interface »ICommandSource« ...... 489 7.3.2 Ein einfaches Panel mit Attached Properties ...... 435 9.2 Eigene Commands mit »ICommand« ...... 490 7.3.3 Bekannte Vertreter ...... 439 9.2.1 Ein Command implementieren ...... 490 7.4 Zusammenfassung ...... 441 9.2.2 Das Command verwenden ...... 491 9.2.3 Das Command von der Logik entkoppeln ...... 492 9.3 Die »wahren« Keyplayer ...... 495 9.3.1 Die Klassen »RoutedCommand« und »RoutedUICommand« ...... 495 8 Routed Events 445 9.3.2 Der »CommandManager« ...... 497 9.3.3 Die Klasse »CommandBinding« ...... 498 8.1 Die Keyplayer ...... 446 9.3.4 Elemente mit einer CommandBindings-Property ...... 499 8.1.1 Die Klassen »RoutedEvent« und »EventManager« ...... 446 9.3.5 Das Zusammenspiel der Keyplayer ...... 500 8.1.2 Die Routing-Strategie ...... 447 8.1.3 Das Interface »IInputElement« ...... 450 9.4 Eigene Commands mit der Klasse »RoutedUICommand« ...... 504 8.1.4 Die Klasse »RoutedEventArgs« ...... 451 9.4.1 Die eigenen Commands in FriendStorage ...... 504 8.1.5 Das Event System ...... 452 9.4.2 Commands mit »InputGestures« versehen ...... 505 9.4.3 Die Klasse »KeyGesture« ...... 505 8.2 Eigene Routed Events ...... 453 9.4.4 Die Klasse »MouseGesture« ...... 506 8.2.1 Ein Routed Event implementieren ...... 453 9.4.5 Die FriendCommands-Klasse mit InputGestures erweitern ...... 506 8.2.2 Klassisches Click-Event ...... 453 9.4.6 CommandBindings zum Window-Objekt hinzufügen ...... 507 8.2.3 Click-Event als Routed Event ...... 454 9.4.7 Die Commands im Menü und in der ToolBar verwenden ...... 509 8.2.4 Das Routed Event als Attached Event verwenden ...... 458 8.2.5 Existierende Routed Events in eigenen Klassen nutzen ...... 460 9.5 Built-in-Commands der WPF ...... 514 8.2.6 Instanz- und Klassenbehandlung ...... 461 9.5.1 Built-in-Commands in FriendStorage ...... 515 9.5.2 Bestehende Commands mit InputBindings auslösen ...... 517 8.3 Die »RoutedEventArgs« im Detail ...... 466 9.5.3 Controls mit integrierten CommandBindings ...... 520 8.3.1 Sender vs. Source und OriginalSource ...... 466 8.3.2 Die Handled-Property ...... 469
12 13 7201.book Seite 14 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 15 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
9.6 Das Model-View-ViewModel-Pattern (MVVM) ...... 523 11.1.5 Setter und EventSetter ...... 585 9.6.1 Die Idee des Model-View-Controller-Patterns (MVC) ...... 523 11.1.6 Styles und Trigger ...... 588 9.6.2 Die Idee des Model-View-ViewModel-Patterns (MVVM) ...... 525 11.2 Trigger ...... 588 9.6.3 Ein MVVM-Beispiel ...... 526 11.2.1 Property-Trigger ...... 590 9.7 Zusammenfassung ...... 531 11.2.2 Die Reihenfolge der Trigger ...... 592 11.2.3 »EnterActions« und »ExitActions« aus »TriggerBase« ...... 593 11.2.4 DataTrigger ...... 595 11.2.5 EventTrigger ...... 596 TEIL II Fortgeschrittene Techniken 11.2.6 »EventTrigger« und »FrameworkElement« ...... 598 11.2.7 Komplexe Bedingungen mit Triggern ...... 601 10 Ressourcen 535 11.2.8 Logisches Oder ...... 601 11.2.9 Logisches Und ...... 602 10.1 Logische Ressourcen ...... 535 11.3 Templates ...... 603 10.1.1 Logische Ressourcen definieren und verwenden ...... 536 11.3.1 Arten von Templates ...... 603 10.1.2 Die Suche nach Ressourcen im Detail ...... 539 11.3.2 Layout mit dem ItemsPanelTemplate ...... 605 10.1.3 Die Suche im Application-Objekt ...... 540 11.3.3 Daten mit DataTemplates visualisieren ...... 606 10.1.4 Systemweite Ressourcen ...... 540 11.3.4 Das Aussehen von Controls mit ControlTemplates anpassen ...... 610 10.1.5 Elemente als Ressourcen verwenden ...... 543 11.3.5 Das Default-ControlTemplate eines Controls ...... 613 10.1.6 Statische Ressourcen ...... 546 11.3.6 Die Verbindung zwischen Control und Template ...... 617 10.1.7 Dynamische Ressourcen ...... 548 11.3.7 Der Inhalt von ContentControls ...... 620 10.1.8 Ressourcen in separate Dateien auslagern ...... 552 11.3.8 Die Items von ItemsControls ...... 620 10.1.9 Logische Ressourcen in FriendStorage ...... 555 11.3.9 Two-Way-Contract zwischen Control und Template ...... 621 10.2 Binäre Ressourcen ...... 558 11.3.10 VisualStateManager statt Trigger verwenden ...... 625 10.2.1 Binäre Ressourcen in .NET ...... 558 11.3.11 Ein Template mit Visual States implementieren ...... 627 10.2.2 Binäre Ressourcen bei der WPF ...... 560 11.3.12 Zustandsübergänge mit Transitions definieren ...... 631 10.2.3 Die Pack-URI-Syntax ...... 563 11.3.13 Das komplette Template im Überblick ...... 633 10.2.4 Auf Dateien im Anwendungsverzeichnis zugreifen ...... 564 11.3.14 Templates in C# ...... 636 10.2.5 In C# auf binäre Ressourcen zugreifen ...... 565 11.4 Styles, Trigger und Templates in FriendStorage ...... 637 10.2.6 Eine binäre Ressource als Splashscreen ...... 568 11.4.1 Der Next-Button ...... 638 10.3 Zusammenfassung ...... 571 11.4.2 Die Image-Objekte der Toolbar-Buttons ...... 640 11.4.3 Die DataGridRows des Freunde-Explorers ...... 642 11.5 Zusammenfassung ...... 645 11 Styles, Trigger und Templates 573
11.1 Styles ...... 573 12 Daten 647 11.1.1 Grundlagen und Keyplayer ...... 574 11.1.2 Styles als logische Ressourcen definieren ...... 577 12.1 Data Binding ...... 648 11.1.3 Einen Style für verschiedene Typen verwenden ...... 581 12.1.1 Data Binding in XAML ...... 648 11.1.4 Bestehende Styles erweitern ...... 583 12.1.2 Data Binding in C# ...... 649
14 15 7201.book Seite 16 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 17 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
12.1.3 Die Binding-Klasse im Detail ...... 650 12.3.12 Mehrere Collections als Datenquelle verwenden ...... 712 12.1.4 Der DataContext ...... 653 12.3.13 Binding an ein ADO.NET-DataSet ...... 712 12.1.5 Die Path-Property im Detail ...... 656 12.4 Benutzereingaben validieren ...... 716 12.1.6 Die Richtung des Bindings ...... 657 12.4.1 Validieren mit »ExceptionValidationRule« ...... 718 12.1.7 Der UpdateSourceTrigger ...... 659 12.4.2 Validieren mit »DataErrorValidationRule« ...... 720 12.1.8 Die Delay-Property des Bindings ...... 660 12.4.3 Validieren mit »NotifyDataErrorValidationRule« ...... 721 12.1.9 Die BindingExpression ...... 661 12.4.4 Validieren mit eigener ValidationRule ...... 725 12.1.10 Bindings entfernen ...... 663 12.4.5 Die Validation-Klasse ...... 726 12.1.11 Debugging von Data Bindings ...... 663 12.4.6 Validieren mehrerer Bindings mit »BindingGroup« ...... 728 12.2 Datenquellen eines Data Bindings ...... 666 12.4.7 Validieren mit der BindingGroup ...... 730 12.2.1 Binding an die Dependency Properties eines Elements ...... 666 12.4.8 Transaktionen mit der BindingGroup ...... 735 12.2.2 Binding an einfache .NET-Properties ...... 667 12.5 Das DataGrid ...... 737 12.2.3 »INotifyPropertyChanged« mit dem CallerMemberName-Attribut ...... 669 12.5.1 Die verwendeten Testdaten ...... 738 12.2.4 Binding an statische Properties ...... 670 12.5.2 Autogenerieren von Columns ...... 740 12.2.5 Binding an logische Ressourcen ...... 672 12.5.3 Unterschiedliche Column-Typen ...... 742 12.2.6 Binding an Quellen unterschiedlichen Typs ...... 673 12.5.4 Columns manuell zum DataGrid hinzufügen ...... 745 12.2.7 Binding an relative Quellen mit »RelativeSource« ...... 676 12.5.5 Die Breite einer Column ...... 747 12.2.8 Mit dem Mode »Self« an eine Property des Target-Elements binden ...... 676 12.5.6 Columns mit der Klasse »DataGridTemplateColumn« ...... 748 12.2.9 »TemplatedParent« für Templates ...... 677 12.5.7 RowDetails anzeigen ...... 750 12.2.10 Mit »FindAncestor« an im Element Tree höher liegende Elemente binden .... 678 12.5.8 Daten gruppieren ...... 752 12.2.11 Mit »PreviousData« an das vorhergehende Datenobjekt binden ...... 679 12.5.9 Die Auswahlmöglichkeiten festlegen ...... 754 12.2.12 Binding der Target-Property an mehrere Quellen ...... 679 12.5.10 Auf ausgewählte Daten zugreifen ...... 755 12.2.13 Die Klasse »MultiBinding« ...... 679 12.5.11 Daten bearbeiten ...... 757 12.2.14 Die Klasse »PriorityBinding« ...... 682 12.5.12 Daten im DataGrid validieren ...... 757 12.2.15 DataSourceProvider für Objekte und XML ...... 683 12.5.13 Sonstige Eigenschaften des DataGrids ...... 761 12.2.16 Die Subklasse »ObjectDataProvider« ...... 684 12.2.17 Die Subklasse »XmlDataProvider« ...... 686 12.6 Daten mit DataTemplates visualisieren ...... 762 12.2.18 Binding an XLinq ...... 690 12.6.1 Auswahl mit der Klasse »DataTemplateSelector« ...... 762 12.6.2 Hierarchische DataTemplates ...... 765 12.3 Data Binding an Collections ...... 692 12.3.1 Der Fallback-Mechanismus ...... 692 12.7 Drag-&-Drop ...... 767 12.3.2 Die CollectionViews der WPF ...... 695 12.8 Daten in FriendStorage ...... 771 12.3.3 Das Interface »ICollectionView« ...... 696 12.8.1 Die Entitäten »Friend«, »Address« und »FriendCollection« ...... 772 12.3.4 Klassen, die »ICollectionView« implementieren ...... 698 12.8.2 Daten im MainWindow ...... 772 12.3.5 Die DefaultView ...... 700 12.8.3 Der Freunde-Explorer ...... 774 12.3.6 Daten filtern, sortieren und gruppieren ...... 701 12.8.4 Die Detailansicht ...... 775 12.3.7 Das Filtern, Sortieren und Gruppieren in C# ...... 702 12.8.5 Previous/Next-Buttons zur Navigation ...... 776 12.3.8 Das Filtern, Sortieren und Gruppieren in XAML ...... 706 12.8.6 Data Binding mit Fallback-Mechanismus ...... 777 12.3.9 »Live Shaping« von Daten ...... 707 12.8.7 Validierung des Vornamens ...... 778 12.3.10 Hinzufügen und Löschen von Daten ...... 709 12.8.8 Droppen eines Bildes ...... 780 12.3.11 Collections auf Worker-Threads bearbeiten ...... 710 12.8.9 Die StatusBar ...... 781
16 17 7201.book Seite 18 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 19 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
12.8.10 Daten im NewFriendDialog ...... 782 13.6 Cached Compositions ...... 841 12.8.11 Speichern in gezippter .friends-Datei ...... 785 13.6.1 BitmapCache für ein Element aktivieren ...... 842 12.9 Zusammenfassung ...... 787 13.6.2 Nebeneffekte des Cachings ...... 843 13.6.3 Elemente mit »BitmapCacheBrush« zeichnen ...... 846 13.7 Effekte ...... 848 TEIL III Reichhaltige Medien und eigene Controls 13.7.1 Die Effect-Klassen ...... 848 13.7.2 »Blur« und »DropShadow« verwenden ...... 849 13.7.3 Properties von »BlurEffect« und »DropShadowEffect« ...... 850 13 2D-Grafik 791 13.7.4 Effekte mit eigenen Pixelshadern ...... 851 13.7.5 Pixelshader mit weiteren Konstanten ...... 860 13.1 Shapes ...... 792 13.8 Bitmaps ...... 863 13.1.1 Das Rectangle ...... 793 13.8.1 BitmapSources – Bildquellen ...... 863 13.1.2 Die Ellipse ...... 794 13.8.2 Bitmap-Operationen ...... 865 13.1.3 Linien mit »Line« und »Polyline« ...... 795 13.8.3 Bitmap-Operationen in FriendStorage ...... 865 13.1.4 Spezielle Formen mit »Polygon« ...... 797 13.1.5 Ein Außerirdischer aus Shapes ...... 799 13.9 Zusammenfassung ...... 866 13.1.6 Die StrokeXXX-Properties der Shape-Klasse ...... 801 13.1.7 Komplexe Shapes mit »Path« ...... 804
13.2 Geometries ...... 804 14 3D-Grafik 869 13.2.1 »RectangleGeometry« und »EllipseGeometry« ...... 806 13.2.2 »LineGeometry« ...... 807 14.1 3D im Überblick ...... 870 13.2.3 Mehrere Geometry-Objekte gruppieren ...... 807 14.1.1 Inhalte einer 3D-Szene ...... 870 13.2.4 Geometries kombinieren ...... 808 14.1.2 2D und 3D im Vergleich ...... 871 13.2.5 Komplexe Formen mit »PathGeometry« ...... 810 14.2 Die Objekte einer 3D-Szene im Detail ...... 873 13.2.6 Die Klasse »StreamGeometry« ...... 813 14.2.1 Das 3D-Koordinatensystem ...... 873 13.2.7 Die Path-Markup-Syntax ...... 814 14.2.2 Der Viewport3D als Fernseher ...... 874 13.2.8 Clipping mit Geometry-Objekten ...... 816 14.2.3 Die richtige Kamera ...... 875 13.3 Drawings ...... 816 14.2.4 Visual3D-Objekte ...... 880 13.3.1 »GeometryDrawing« und »DrawingGroup« ...... 817 14.2.5 Model3D-Objekte ...... 881 13.3.2 »ImageDrawing« und »VideoDrawing« ...... 819 14.2.6 »GeometryModel3D« aufbauen ...... 882 13.3.3 Ein Außerirdischer aus Geometries und Drawings ...... 820 14.2.7 Licht ins Dunkel bringen ...... 888 13.4 Programmierung des Visual Layers ...... 823 14.2.8 Transformationen ...... 891 13.4.1 Die Klasse »DrawingContext« ...... 823 14.2.9 Verschiedene Materialien ...... 894 13.4.2 DrawingVisual einsetzen ...... 825 14.2.10 Texturen ...... 895 13.4.3 Visual-Hit-Testing ...... 827 14.2.11 Normalen ...... 898 13.5 Brushes ...... 828 14.3 Benutzerinteraktion mit 3D-Objekten ...... 903 13.5.1 Der »SolidColorBrush« und die Color-Struktur ...... 829 14.3.1 Interaktivität in »ModelVisual3D« mit Visual-Hit-Testing ...... 903 13.5.2 Farbverläufe mit GradientBrushes ...... 831 14.3.2 Interaktivität mit »UIElement3D« ...... 904 13.5.3 TileBrushes ...... 836 14.3.3 Interaktive 2D-Elemente auf 3D-Objekten ...... 906
18 19 7201.book Seite 20 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 21 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
14.4 Komplexe 3D-Objekte ...... 908 15.6.2 Easing Functions in Basis-Animationen ...... 970 14.4.1 Landschaft im Code generieren ...... 908 15.6.3 Easing Functions in Keyframe-Animationen ...... 972 14.4.2 Kugel erstellen ...... 910 15.6.4 Eigene Easing Functions erstellen ...... 974 14.4.3 Komplexe 3D-Objekte mit Third-Party-Tools erstellen ...... 912 15.7 Low-Level-Animationen ...... 976 14.5 Zusammenfassung ...... 913 15.8 Zusammenfassung ...... 980
15 Animationen 915 16 Audio und Video 981
15.1 Animationsgrundlagen ...... 916 16.1 Audio (.wav) mit »SoundPlayerAction« und »SoundPlayer« ...... 981 15.1.1 Voraussetzungen für Animationen ...... 916 16.1.1 Audio mit »SoundPlayerAction« (XAML) ...... 982 15.1.2 Übersicht über die Animationsarten und -klassen ...... 917 16.1.2 Audio mit »SoundPlayer« (C#) ...... 983 15.1.3 Timelines und Clocks ...... 920 16.2 Audio und Video mit »MediaPlayer« (C#) ...... 985 15.1.4 Das Interface »IAnimatable« ...... 923 16.2.1 Einfaches Abspielen ...... 985 15.2 Basis-Animationen in C# ...... 924 16.2.2 Audio mit dem MediaPlayer ...... 985 15.2.1 Start- und Zielwert mit »From«, »To« und »By« ...... 925 16.2.3 Videos abspielen ...... 986 15.2.2 Animation nur mit »To« ...... 926 16.2.4 Steuerung mit »MediaClock« und »MediaTimeline« ...... 988 15.2.3 Animation nur mit »From« ...... 927 16.3 Audio und Video mit »MediaElement« (XAML) ...... 991 15.2.4 Animation mit »From« und »By« ...... 928 16.3.1 Einfaches Abspielen ...... 992 15.2.5 Dauer, Startzeit und Geschwindigkeit ...... 929 16.3.2 Steuerung mit Methoden (unabhängiger Modus) ...... 994 15.2.6 Rückwärts und Wiederholen ...... 931 16.3.3 Steuerung mit »MediaTimeline« (Clock-Modus) ...... 994 15.2.7 Die Gesamtlänge einer Timeline ...... 933 16.3.4 Storyboard mit »MediaTimeline« und »AnimationTimeline« ...... 997 15.2.8 Wiederholen mit neuen Werten ...... 933 16.3.5 Snapshots von Videos ...... 999 15.2.9 Beschleunigen und Abbremsen ...... 935 15.2.10 Das Füllverhalten einer Animation ...... 936 16.4 Zusammenfassung ...... 1001 15.2.11 Eine Animation mit »AnimationClock« steuern ...... 938 15.2.12 Animationen in FriendStorage ...... 942
15.3 Basis-Animationen in XAML ...... 943 17 Eigene Controls 1003 15.3.1 Eine einfache Animation in XAML ...... 946 15.3.2 Das Storyboard als Timeline-Container ...... 950 17.1 Custom Controls ...... 1004 15.3.3 Animationen mit »ControllableStoryboard« steuern ...... 952 17.1.1 Die Struktur eines Custom Controls ...... 1005 15.4 Keyframe-Animationen ...... 955 17.1.2 Der zu erstellende VideoPlayer ...... 1008 15.4.1 Lineare Keyframe-Animationen ...... 956 17.1.3 Klassenname anpassen ...... 1008 15.4.2 SplineKeyframe-Animationen ...... 958 17.1.4 Template-Parts definieren ...... 1010 15.4.3 Animationen mit diskreten Keyframes ...... 960 17.1.5 Dependency Properties erstellen ...... 1013 17.1.6 Routed Events implementieren ...... 1017 15.5 Pfad-Animationen ...... 963 17.1.7 Commands unterstützen ...... 1018 15.6 Easing Functions ...... 966 17.1.8 Das Aussehen des lookless Controls festlegen ...... 1022 15.6.1 Grundlagen der Easing Functions ...... 966 17.1.9 Das Control testen ...... 1026
20 21 7201.book Seite 22 Donnerstag, 5. September 2019 8:43 08 7201.book Seite 23 Donnerstag, 5. September 2019 8:43 08
Inhalt Inhalt
17.1.10 Optional weitere Theme-Styles anlegen ...... 1028 18.3.3 Die AnchoredBlocks »Figure« und »Floater« ...... 1086 17.1.11 Templates auf Windows-Ebene definieren ...... 1031 18.3.4 Controls zum Betrachten ...... 1089 17.2 Custom Control mit Visual States ...... 1035 18.4 Annotationen ...... 1091 17.2.1 Visual States im Code implementieren ...... 1035 18.5 XPS-Dokumente (Fixed-Dokumente) ...... 1096 17.2.2 States für andere sichtbar machen ...... 1038 18.5.1 FlowDocument als XPS speichern ...... 1096 17.2.3 States im Default-ControlTemplate unterstützen ...... 1039 18.5.2 Ein XPS-Dokument laden und anzeigen ...... 1100 17.2.4 Den VideoPlayer mit Visual States testen ...... 1041 18.5.3 Die Inhalte eines XPS-Dokuments ...... 1101 17.3 User Control ...... 1042 18.5.4 XPS in C# mit FixedDocument & Co. erstellen ...... 1105 17.3.1 Die Struktur eines User Controls ...... 1042 18.6 Drucken ...... 1107 17.3.2 Das selbst erstellte PrintableFriend-Control ...... 1044 18.6.1 Einfaches Ausdrucken ...... 1108 17.3.3 Das UI des Controls definieren ...... 1045 18.6.2 Drucken mit »PrintQueue« ...... 1109 17.3.4 Properties in der Codebehind-Datei erstellen ...... 1046 18.6.3 Festlegen von Druckeigenschaften mit »PrintTicket« ...... 1110 17.3.5 Die Content-Property festlegen ...... 1048 18.6.4 Drucken mit »PrintDialog« ...... 1111 17.4 Alternativen zu Custom Control und User Control ...... 1049 18.7 Dokumente in FriendStorage ...... 1112 17.4.1 Wann sollte man die OnRender-Methode überschreiben? ...... 1049 18.7.1 Hilfe mit Flow-Dokument ...... 1112 17.4.2 Adorner erstellen und Elemente damit ausschmücken ...... 1050 18.7.2 Export der Freundesliste als XPS ...... 1113 17.5 Zusammenfassung ...... 1056 18.7.3 Drucken der Freundesliste ...... 1118 18.8 Zusammenfassung ...... 1119
18 Text und Dokumente 1059 TEIL IV Interoperabilität und Apps 18.1 Text ...... 1060 18.1.1 »FrameworkContentElement« als Basis für Text ...... 1060 19 Standard-Dialoge, Windows Taskbar und mehr 1123 18.1.2 Formatierung mit Spans ...... 1062 18.1.3 Formatierung mit den Properties aus »TextElement« ...... 1064 19.1 Standard-Dialoge ...... 1123 18.1.4 Elemente im Text mit »InlineUIContainer« ...... 1066 19.1.1 Der SaveFileDialog ...... 1124 18.1.5 Fonts und Typefaces ...... 1067 19.1.2 Der OpenFileDialog ...... 1124 18.1.6 Typografie ...... 1068 18.1.7 Die FormattedText-Klasse ...... 1069 19.2 Integration in die Windows Taskbar ...... 1125 18.1.8 Texteffekte ...... 1071 19.2.1 Übersicht der Möglichkeiten ...... 1126 18.1.9 Nützliche Eigenschaften der TextBlock-Klasse ...... 1073 19.2.2 Thumb-Buttons im Vorschaufenster ...... 1128 19.2.3 Ein Overlay-Bild auf dem Taskbar-Button ...... 1131 18.2 Das Text-Rendering beeinflussen ...... 1075 19.2.4 Eine Fortschrittsanzeige auf dem Taskbar-Button ...... 1132 18.2.1 Text klar zeichnen ...... 1075 19.2.5 Den Ausschnitt im Thumbnail festlegen ...... 1134 18.2.2 Text für Animationen optimieren ...... 1076 19.2.6 Eine JumpList mit JumpTasks ...... 1135 18.2.3 Den Algorithmus für das Anti-Aliasing festlegen ...... 1077 19.2.7 JumpList mit JumpTasks und JumpPaths ...... 1136 18.2.4 Den ClearType-Algorithmus aktivieren ...... 1078 19.2.8 JumpList mit letzten und häufigen Elementen ...... 1139 18.3 Flow-Dokumente ...... 1080 19.3 Deployment ...... 1140 18.3.1 Die Klasse »FlowDocument« ...... 1080 18.3.2 Die fünf Block-Arten ...... 1082 19.4 Zusammenfassung ...... 1141
22 23 7201.book Seite 24 Donnerstag, 5. September 2019 8:43 08
Inhalt
20 Interoperabilität 1143
20.1 Unterstützte Szenarien und Grenzen ...... 1144 20.1.1 Mögliche Interoperabilitätsszenarien ...... 1144 20.1.2 Grenzen und Einschränkungen ...... 1145 20.2 Windows Forms ...... 1146 20.2.1 Windows Forms in WPF ...... 1147 20.2.2 WPF in Windows Forms ...... 1155 20.2.3 Dialoge ...... 1157 20.3 ActiveX in WPF ...... 1159 20.4 Win32 ...... 1162 20.4.1 Win32 in WPF ...... 1162 20.4.2 Win32-Nachrichten in WPF abfangen ...... 1173 20.5 Zusammenfassung ...... 1176
21 Universal Windows Apps und WinUI 1177
21.1 Einführung ...... 1177 21.1.1 Windows Store Apps in Windows 8 ...... 1178 21.1.2 Universal Windows Apps in Windows 10 ...... 1179 21.1.3 Das WinUI-Framework ...... 1180 21.1.4 Universal Windows Apps/WinUI vs. WPF ...... 1181 21.2 Die FriendViewer-App erstellen ...... 1182 21.2.1 Die Tools installieren ...... 1182 21.2.2 Das Projekt anlegen ...... 1183 21.2.3 Projektstruktur und Dateien ...... 1184 21.2.4 Die MainPage befüllen ...... 1185 21.2.5 Visuelle Zustände für adaptives Layout ...... 1190 21.2.6 Wie geht es weiter? ...... 1194 21.3 Zusammenfassung ...... 1194
Index ...... 1195
24