Blog

Einstieg in WPF – Erlebnisse eines ehemaligen Windows Forms Entwicklers

Jochen Maurer
31. August 2012

Haben Sie schon einmal ernsthaft daran gedacht, von Windows Forms (WinForms) auf WPF umzusteigen? Die neue Anwendung nicht mehr nach altbekanntem Muster schreiben sondern etwas Neues zu wagen? Um ehrlich zu sein, bis vor ein paar Monaten habe ich mir keine Gedanken bzgl. eines Umstiegs gemacht. So wohl vertraut ist mir die Windows Forms Welt. Darin kenne ich mich aus, WPF müsste ich neu erlernen. Also blieb es bei einem Testprojekt und meine Anwendungen blieben weiter in Windows Forms. Als ich dann Anfang dieses Jahres nach fast 15 Jahren als Entwickler in der Finanzbranche zu Centigrade gekommen bin, war hier der Umstieg längst vollzogen. Werfen Sie mal einen Blick in unsere Blog-Artikel zu diesem Thema! Meine Kollegen im Bereich Design Engineering arbeiten schon seit einigen Jahren mit WPF. Insbesondere die jüngeren Designer und Design Engineers kannten Windows Forms gar nicht aus der Praxis, sondern – wenn überhaupt – nur aus dem Studium. Viele Unternehmen setzen WPF ein, aber trotz der bereits vierten Version der Technologie befinden sich noch einige von ihnen in der Einführungsphase. Aber aus eigener Erfahrung kann ich nur berichten – das ist nicht überall so. Gerade in der Finanzbranche werden weiterhin eher trist wirkende Anwendungen in Windows Forms gebaut. Dabei geht es doch auch ansprechender…

So begann für mich ein neues Kapitel in meiner Programmiererlaufbahn. Mit einer gesunden Portion Skepsis bin ich in mein erstes WPF Projekt eingestiegen – und ich war sofort begeistert. Einige meiner Erfahrungen habe ich gesammelt und in diesem Artikel zusammengefasst.

Formulardesign in Expression Blend – Wie style ich meine WPF-Anwendung?

Wer kennt ihn nicht, den guten alten Formulardesigner für Windows Forms. Element aus der Toolbox auswählen, auf den Workspace ziehen, Größe und Text anpassen und schon ist sie fertig, meine Control. Ging doch schnell, sieht aber irgendwie ziemlich nach Standard aus. Mit den Bordmitteln ist hier nicht viel rauszuholen. Button bleibt Button, Checkbox bleibt Checkbox. Das hat mich 1997 beim Einstieg in Visual Basic 5.0 sehr angesprochen. Alle bisher verwendeten Programmiersprachen (Pascal, Cobol) hatten keine graphische Oberfläche sondern nutzten für Ein- und Ausgabe ausschließlich die Konsole. Heute löst Windows Forms jedoch keinen Begeisterungssturm mehr aus. Die optischen Verbesserungen seit Einführung von Windows Forms sind recht überschaubar. Gibt es da nichts Neues?

Auf den ersten Blick bin ich ein wenig ernüchtert bei meinen ersten Kontakten mit WPF, der Designer in Visual Studio verhält sich in dieser Technologie fast gleich. Ich ziehe einen RadioButton aus der Toolbox und es erscheint eine Windows Standard Control. War das wirklich schon alles? Mein Kollege gibt mir einen Tipp: Schließe dein Projekt und öffne es neu im eigentlichen WPF Designer Werkzeug – Expression Blend. Ein paar Klicks und schon bin ich im Template, also dem Bauplan, meines RadioButton angelangt. Mein Kollege zeigt mir, welche Änderungen es benötigt, um aus einem langweiligen einen ansprechenden RadioButton zu stylen. Den ursprünglichen RadioButton haben wir innerhalb kürzester Zeit in seine Einzelteile zerlegt und ihn aus völlig anderen Bestandteilen neu aufgebaut. Ein Farbverlauf hier, ein Schatten-Effekt da. Wir realisieren noch schnell die States und schon ist er nicht mehr wieder zu erkennen. Während wir den Style des RadioButton verändern, sehe ich, wie der Xaml-Editor fleißig Code generiert.

A: Standard WPF Style, B: Custom Style, C: Windows 8 Style UI

Xaml – Design per Code leichtgemacht

Das also ist Xaml-Code. Ich bin etwas ratlos und frage meinen Kollegen: „Enthält dieser Xaml-Code tatsächlich alle Änderungen, die wir gerade per Designer durchgeführt haben? Kann ich also meinen kompletten Button auch stylen, in dem ich Zeile für Zeile Xaml schreibe?“ Als Antwort erhalte ich ein: „Ja, klar! Aber noch viel besser, du kannst den Style und das Template für deinen Button auch auslagern und ihn auch einer anderen Button-Instanz zuweisen. Dafür gibt es das ResourceDictionary.“ Mein Kollege zeigt mir, wie man Template und Style einer Control in dieses Dictionary auslagert. In den verschiedenen Dictionaries liegen bereits allerlei andere Styles, Farben, Brushes, etc. Alles ausgelagert – per Key kann ich jederzeit auf eine dieser Ressourcen zugreifen. Das will ich natürlich ausprobieren. Ich verweise in meinem Xaml einfach auf das Dictionary und wähle für meinen Button einfach einen anderen Style. Und schon sieht er wieder vollkommen anders aus.

Designen ohne Programmierkenntnisse – Wirklich?

Wir arbeiten weiter und stylen das Layout unserer Benutzeroberfläche. Bisher haben wir noch keine Zeile C# Code geschrieben. „Langweilig!“ – sagt mir ein erster Entwicklerreflex. Aber toll ist es irgendwie trotzdem. Als reiner Entwickler kann ich mich in Zukunft ausschließlich auf die Realisierung der Programmlogik konzentrieren. Die Interaktion mit der Präsentationsschicht betrifft mich nur noch sekundär.

„Die Programmlogik ist bereits in Teilen vorhanden“, sagt mein Kollege. „Sie kommt von unserem Auftraggeber. Wir nehmen darauf keinen Einfluss.“ Per Bindings verbinden wir ausschließlich unsere Oberfläche mit dem darunterliegenden Programmcode. Da leuchten zum ersten Mal so richtig meine Augen! Eine echte Trennung von Präsentationsschicht und -logik. Ich kann also nach meinen Vorgaben die Oberfläche von einem Designer erstellen lassen und hänge sie einfach so an meine Anwendung? Das ist fast so schön um wahr zu sein. Und doch geht es. Ich kann meine komplette Anwendung umgestalten lassen. Und das ohne eine einzige Zeile C# Code. Aber wie geht das?

MVVM – Kooperation zwischen Designer und Entwickler

Die Lösung lautet MVVM (Model View ViewModel). Diese Architektur erlaubt die komplette Trennung von Präsentationdarstellung und -logik. Die View besteht nun fast ausschließlich aus Xaml-Code. Diese kann beliebig von einem Designer Engineer erzeugt und verändert werden, selbst dann schon, wenn ihm das Model (die Programmlogik) noch gar nicht vollständig vorliegt. Einzig und allein die Schnittstellen des ViewModels muss er kennen. Das ViewModel enthält die Interaktion beider Schichten. Ich habe zudem im Gegensatz zu Windows Forms die Möglichkeit des sog. „TwoWay Bindings“. Habe ich z.B. eine TextBox und möchte deren Inhalt verändern, bleibt mir nur die Zuweisung von Hand im Code. DataBindings gibt es zwar auch in Windows Forms, aber leider nur auf Datenquellenebene. Ein Binden an eine String Variable ist nicht möglich. Das geht aber Dank der Bindings in WPF problemlos. Dank MVVM und den DataBindings synchronisieren sich nun TextBox und Variable in beide Richtungen. Diese Art und Weise der Bindings ermöglicht ein echtes Loslösen des Layouts. Aus dem Code spreche ich nirgends eine Control direkt an, sondern kommuniziere ausschließlich indirekt via Change-Events über die im ViewModel angelegten Properties. Spaghetti Code mit kruder GUI Logik gehört damit der Vergangenheit an und ich kann das korrekte Verhalten des ViewModels sogar mit einem Unit-Test verifizieren. Aber geht das wirklich immer so einfach? Kann alles im View Layer per Designer und Xaml-Code gelöst werden?

Behavior, Converter, Trigger – Erste Arbeit für Entwickler?

Nein, ganz so einfach ist es doch nicht. Zwischen View und ViewModel befindet sich noch eine Art Zwischenschicht mit Komponenten, die eher dem View-Layer zugerechnet werden. Diese Komponenten bilden sprichwörtlich den Kleister zwischen den View und ViewModel Schicht. Nehmen wir als Beispiel eine einfache Berechnung zwischen zwei Zahlen. Im Formular befinden sich drei Textfelder, Feld 1 und 2 enthalten die zu berechnenden Werte, Feld 3 das Ergebnis. Im Xaml-Code ist diese Berechnung nicht so einfach durchzuführen. Also brauchen wir an dieser Stelle einen sog. Converter, der im Xaml per Binding an alle drei Textfelder gebunden wird und somit bei jeder Änderung der Eingabewerte eine neue Berechnung ausführt. Gerade einfache Berechnungen oder Konvertierungen gehören nicht in die Programmlogik sondern werden als Converter ausgelagert. Und an dieser Stelle darf endlich programmiert werden! Hier ist der Engineer im Design Engineer gefragt und weniger der Designer. Neben Convertern gibt es auch noch sog. Behaviors und Trigger… diese aber zu erklären würde den Rahmen sprengen. Ich kann nur sagen – sie vereinfachen die Zusammenarbeit zwischen Entwicklern und Designern nochmals um ein vielfaches.

Effekte und PixelShader – Ausnutzen der Hardwarebeschleunigung

Genau so sieht es mit dem Thema „visuelle Effekte“ aus. Stellen Sie sich vor, sie möchten einen „Glow“-Effekt realisieren, wenn Sie einen Button anklicken. Dieser Effekt soll natürlich über allen anderen Controls leuchten, die in direkter Umgebung liegen. Dazu wäre es schön, wenn der Effekt nicht einfach ein halb durchsichtiges Rechteck mit einem Farbverlauf in seinem Inneren ist, sondern ein richtig schönes Glühen (wie z.B. in Photoshop mit einem Blendmode) in der Form unserer Control als Silhouette zu sehen ist.

Hier wird ein Derivat der WPF Effect-Klasse benötigt – und damit auch wieder C# Code. Wir wählen also die Control, ziehen auf diese unseren Effect, wählen einen BlendMode und ein Objekt aus, welches die Farbe für unseren Effekt enthält. Im Effect selbst muss nun ein PixelShader angesteuert werden. Welchen Vorteil bietet uns das? „Normale“ Effekte in WPF (z.B. der DropShadowEffect) sind meist recht umfangreich ausgestattet und damit nicht besonders performant. Gerade auf Industrie-PCs (wie in unserem Kundenkreis oft eingesetzt) muss eine einfache, schnelle Lösung her. Um den schon besprochenen BlendMode zu realisieren, integrieren wir daher einen PixelShader. Dieser enthält nur den eigentlichen Effekt ohne große Einstellmöglichkeiten. PixelShader werden in HLSL beispielsweise in dem großartigen Shazzam Editor programmiert und arbeiten besonders performant, da sie direkt in der GPU der Grafikkarte gerendert werden. Das entlastet beim Rendern der Oberfläche die CPU. Mittels eines Behaviors kann ich diesen Effekt jetzt auch noch über die eigentliche Content-Schicht in WPF – nämlich in den AdornerLayer – platzieren. Das ist wichtig, damit auch der Hintergrund Einfluss auf die Farbe des Glühens hat. Dieses Schichtenmodell ist in dieser Form übrigens nicht in Windows Forms enthalten – das Realisieren von Effekten leider auch nicht.

Skalierbarkeit – Optimale Sicht in jeder Auflösung

Was uns zum nächsten Punkt bringt: die Skalierbarkeit der Oberfläche. Haben Sie mal versucht eine Windows Forms Anwendung zu skalieren? Sie können die Controls an den Screen binden und so deren Größe dynamisch ändern und sie alignieren – aber skalieren? Während meiner Zeit als IT-Verantwortlicher habe ich so einige Merkwürdigkeiten zu Gesicht bekommen. Eine ehemalige Kollegin hatte an ihrem 24“ LCD Display eine Auflösung von 800×600 Pixel eingestellt. Normal ist bei diesem Display eine Auflösung von 1680×1080. Auf die Frage, warum sie das so eingestellt hat, bekam ich die Antwort: „Weil ansonsten alles so klein ist!“ Die Anwendung, in der sie hauptsächlich arbeitet, ist für eine Auslösung von 1024×768 Pixel konzipiert. Wenn man nun an einem so großen Display arbeitet und das Fenster der Anwendung größer zieht, hat man nichts gewonnen. Alle Controls bleiben gleich groß. Ist das schöne, hochauflösende LCD Display damit hinfällig? Nein, in WPF kann ich mein Layout so gestalten, dass ich seine Größe individuell skalieren kann – natürlich ohne Qualitätsverluste, da alles vektorbasiert gerendert wird. So sieht eine WPF-Anwendung auf allen möglichen Screentypen und Pixeldichten immer gestochen scharf aus. Gerade auf Maschinenterminals, die meist recht unterschiedliche Auflösungen haben, ist das ein absolutes Muss.

Touch-Bedienung – Am besten in WPF realisieren

Apropos Maschinenterminals – diese haben meist keine Eingabegeräte wie Maus oder Tastatur sondern werden im Regelfall per Touch bedient. Gerade bei komplexer Funktionalität sind Gesten mit einem oder mehreren Fingern unumgänglich. Jeder, der heute ein Smartphone oder einen Tablet-Computer besitzt, kennt diese Gesten. Auch die Bedienung im bald erscheinenden Windows 8 ist dafür ausgelegt. Haben Sie sich daher schon mit dem Thema Touch-Bedienung und komplexe Gesten in Windows Forms beschäftigt? Nein? Lassen Sie es besser, die Implementierung der Touch-Bedienung in Windows Forms ist so gut wie nicht vorhanden. Mittels einer Ein-Finger-Geste Objekte anklicken lässt sich noch problemlos darstellen. Alles, was darüber hinausgeht, ist nicht oder nicht in vernünftigem Rahmen zu realisieren. Machbar ist zwar bekanntlich (fast) alles, doch weshalb nimmt man nicht gleich die bordeigenen Mittel in WPF? Das geht deutlich einfacher und selbst komplexe Gesten lassen sich ohne allzu großen Aufwand realisieren.

Datenanbindung – WPF und das Entity Framework

Bleibt noch eins meiner Lieblingsthemen – die Anbindung von Datenbanken. Ich habe lange Zeit mit Datenzugriffen über DAO, ADO bzw. ADO.Net gearbeitet und das Entity Framework erst vor recht kurzer Zeit kennengelernt. Gerade bei Themen, in denen man sich mit seinem Wissen sicher fühlt, ist man Neuem gegenüber bekanntlich besonders kritisch. Aber auch hier gibt es nichts zu mäkeln. Die Anbindung an WPF erfolgt wie in Windows Forms auch per Data-Binding. Bei Elementen, die mehrere Datensätze enthalten können (z.B. ComboBox, Grid), wird als Datenquelle eine ObservableCollection hinterlegt, die sich automatisch aktualisiert und deren Inhalt somit immer den aktuellen Datenstand repräsentiert. Der eigentliche Zugriff auf die Daten erfolgt ausschließlich in der Programmlogik und damit nicht im Bereich des Designs. Das hat den riesigen Vorteil, dass sich der Design Engineer beim Konstruieren der Views überhaupt nicht mit dem Thema Datenherkunft beschäftigen muss. Der Designer kann in Expression Blend dank sog. Sampledaten sogar zur Designzeit, also nicht zur Laufzeit, mit Dummy Daten arbeiten und diese Stylen, bis diese dann schließlich mit den echten Datenbankdaten ersetzt werden. Das sollte zwar auch für Windows Forms Anwendungen gelten, dort können jedoch die Data-Bindings nicht verwendet werden, wenn keine direkte Kommunikation zur Datenquelle stattfindet. Trotz besonders strengem Blick wollten mir auch hier keine Nachteile von WPF zu Windows Forms auffallen.

Fazit – Was von Windows Forms übrig blieb

Zugegeben, es ist nicht ganz einfach mit WPF. Ein bisschen Lernen und Üben muss man schon. Insbesondere der Wechsel zwischen der festen Verdrahtung von Oberfläche und Logik in Windows Forms hin zum MVVM-Pattern in WPF sorgt am Anfang für Schwierigkeiten. Hat man diese überwunden und sich die Logik verinnerlicht, sprechen die Vorteile von WPF schnell für sich. Wirklich ernstzunehmende Vorteile bietet Windows Forms gegenüber WPF heutzutage nicht mehr. Die guten Ansätze wurden in WPF übernommen und deutlich verbessert. Dazu hat man neue Features in den Bereichen Grafik und Effekt realisiert. Weiß man mit WPF umzugehen, ist auch die Performanzfrage nicht mehr so dramatisch. Für mich als Entwickler sind auf einen Schlag ungeahnte Welten bzgl. Design und Usability entstanden. Eine Anwendung kann jetzt neben ihrer (hoffentlich) tollen Funktionalität auch mit einer augenfreundlichen Oberfläche und einer herausragenden Bedienbarkeit punkten. Und ganz unter uns, wer sehnt sich heute in Zeiten von Smartphone und Tablet- Computer noch an sein VT-100 Terminal zurück…

Wenn Sie gerne mehr über unsere Herangehensweise an Projekte und Services herausfinden möchten, lesen Sie gerne auf unserer Engineering Seite weiter.

Ein Jahr später: Nützliche WPF Werkzeuge (nicht nur für ehemalige WinForms Entwickler)

Nach gut einem Jahr voller neuer Erfahrungen in WPF möchte ich diesem Artikel ein kleines Update gönnen und den Blick auf ein paar Werkzeuge lenken, die mir im Laufe des vergangenen Jahres die Arbeit mit WPF deutlich vereinfacht haben:

  • WPF Inspector: Untersucht eine laufende WPF Anwendung und hilft damit bei der Fehlerbehebung von Layout und Styling
  • XamlBoard: Unterstützt bei der Erstellung von WPF Themes, erleichtert das Styling von Screens und optimiert XAML ResourceDictionaries hinsichtlich ihrer Performance
  • Snoop: Liest den Visual Tree einer laufenden WPF Anwendung aus
  • Xaml Styler: Stylt den Xaml Code in ein vorher definiertes Format und ermöglich somit einen sauberen Commit in einem Projekt mit mehreren Entwicklern
  • Shazzam: Editor mit Preview Funktion zum einfachen Erstellen von PixelShadern. Der kompilierte PixelShader und die generierte Effekt-Klasse können direkt ins Projekt eingebunden werden
  • Dependency Property Generator: Der Name spricht schon für sich 😉

Anschauen, herunterladen und ausprobieren! All diese Werkzeuge bieten eine ideale Ergänzung zur Funktionalität von Visual Studio und Blend.

 

Wir haben Ihr Interesse geweckt? Schauen Sie sich unsere Leistungen an!

UX Engineering

 

Alle genannten Marken oder eingetragene Marken sind Eigentum der jeweiligen Markeninhaber.

Möchten Sie mehr zu unseren Leistungen, Produkten oder zu unserem UX-Prozess erfahren?
Wir sind gespannt auf Ihre Anfrage.

Senior UX Manager
+49 681 959 3110

Bitte bestätigen Sie vor dem Versand Ihrer Anfrage über die obige Checkbox, dass wir Sie kontaktieren dürfen.