Tutorialreihe <WPF lernen/>

    • WPF

    SSL ist deaktiviert! Aktivieren Sie SSL für diese Sitzung, um eine sichere Verbindung herzustellen.

    Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

      Tutorialreihe <WPF lernen/>

      WPF verständlich und anhand von Praxisbeispielen erklärt


      Autor: Sascha Patschka

      Inhaltsverzeichnis (inkrementell)

      ___1. Vorstellung
      _____1.1 Einleitung
      _____1.2 Aufbau der Tutorialreihe

      ___2. Grundlagen der WPF
      _____2.1 Einführung in die WPF
      ________2.1.1 Die wichtigsten Controls und deren Verwendung
      ______________2.1.1.1 Videocast: Die wichtigsten Controls und ihr Verhalten
      ______________2.1.1.2 Videocast: Style, Templates und Trigger
      ______________2.1.1.3 Videocast: Controls eine neue Optik verpassen
      ________2.1.2 XAML Namespaces (Cooming soon)
      ______________2.1.2.1 Kurze Theorie
      ______________2.1.2.2 Anwendung interessanter Namespaces
      ______________2.1.2.3 Eigene Namespaces erstellen und integieren
      ________2.1.3 Resourcen (Cooming soon)
      ______________2.1.3.1 Was sind Resourcen, was bringen sie mir
      ______________2.1.3.2 Unterschied StaticResource und DynamicResource
      ________2.1.4 Binding und das Bindingsystem (Cooming soon)
      ______________2.1.4.1 Was ist DataBinding? Das Konzept dahinter
      ______________2.1.4.2 Binding anhand einfacher Beispiele und Klassen
      ______________2.1.4.3 DesignTime Support für Binding
      ______________2.1.4.4 Binding über Converter
      ______________2.1.4.5 Binding über DataTemplates
      ______________2.1.4.6 Binding an Collections. Warum ICollectionViewSource? Filtern, Sortieren, Gruppieren ohne viel Aufwand
      ______________2.1.4.7 Validierung von Benutzereingaben
      ______________2.1.4.8 Rücksicht nehmen auf die aktuelle Culture
      ________2.1.5 Dependency Properties (In planing)
      ______________2.1.5.1 Was sind Dependency Properties und wie unterscheiden sie sich von normalen Properties
      ______________2.1.5.2 Eigene DependencyProperties implementieren
      ________2.1.6 Markuperweiterungen
      ______________2.1.6.1 Kurze Theorie
      ______________2.1.6.2 Beispiele Anhand von Resourcen und Styles
      ________2.1.7 Attached Properties
      ______________2.1.7.1 Kurze Theorie (wozu Attached Properties)
      ______________2.1.7.2 Beispiele Anhand vom Grid und dem DockPanel
      ______________2.1.7.3 Eigene Attached Properties erstellen ;)
      ________2.1.8 Attached Events
      ______________2.1.8.1 Wir gehen gleich in die Praxis, es gibt nicht viel zu sagen, soll trotzdem erwähnt sein
      ________2.1.9 Inputs und Commands
      ______________2.1.9.1 Die Input-API
      ______________2.1.9.2 Tastatur und Mausklassen
      ______________2.1.9.3 Eventrouting (Direct, Bubbling, Tunneling)
      ______________2.1.9.4 Keyboard, Mouse und TeytInput
      ______________2.1.9.5 Touch und Multitouch (wird ja immer wichtiger)
      ______________2.1.9.6 Focus (Der Unterschied zwischen Keyboardfocus und Logicalfocus)
      ______________2.1.9.7 Commands (Integrierte und Eigene)
      ______________2.1.9.8 Die RelayCommand Klasse
      ______________2.1.9.9 CommandBinding und CommandParameter
      ___3. Eine Telefonbuch Applikation unter WPF (ohne Binding)
      _____3.1 Hauptfenster erstellen und Funktionen festlegen
      _____3.2 Ein primitives Telefonbuch rein mit CodeBehind ala WinForms
      _____3.3 Fazit
      ___4. Eine Telefonbuch Applikation unter WPF (mit Binding der CodeBehind)
      _____4.1 Umbau der TelefonbuchA Applikation unter WPF (mit Binding der CodeBehind)
      _____4.2 Fazit - Was ist besser, was schlechter
      ___5. Das MVVM Pattern
      _____5.1 Was ist das MVVM Pattern?
      _____5.2 Wann MVVM und wann nicht?
      _____5.3 Welchen Mehrwert kann ich aus dem Pattern gewinnen?
      _____5.4 MVVM und CodeBehind - verboten?
      _____5.5 Model - View - ViewModel - Wars das?
      _____5.6 Erstellen einer korrekten MVVM Projektmappe in VisualStudio
      ___6. Unser Telefonbuch in MVVM
      _____6.1 Projekt anlegen und Struktur besprechen
      _____6.2 Das Model erstellen
      _____6.3 ViewModel - Der Core - was benötigen wir alles ehe wir anfangen können mit unserem Programm
      _____6.4 Wie Messageboxen, Dialoge, MouseCursor oder TaskbarInfo steuern wenn ich die View nicht kenne?
      _____6.5 Jetzt anfangen? Ne? Warum?
      _____6.6 Das MainViewModel erstellen
      _____6.7 ....
      _____6.8 Fazit zum MVVM Pattern
      ___7. Lokalisierung und Globalisierung
      _____7.1 Lokalisierung nur mit Boardmitteln
      _____7.2 Lokalisierung mit schwung (unter zuhilfenahme von zwei NuGet-Paketen)
      _____7.3 Globalisierung (Datum, Währung, usw.)
      _____7.4 Lokalisieren von Werten aus Fremsystemen (DB, XML usw.)
      _____7.5 Gute Hilfsprogramme und Helferlein
      ___8. UnitTests und IntergrationTests
      _____8.1 Wozu UnitTests?
      _____8.2 Wie schreibe ich Tests (Grundlagen)
      _____8.3 Testen unseres ViewModels möglich?
      _____8.4 ...
      _____8.5 ...
      _____8.6 Fazit
      ___9. Repository (DataAccessLayer)
      _____9.1 Noch einen Schritt weiter? Wozu?
      _____9.2 Besprechen und Aufsetzen eines Repositorys
      _____9.3 Wir bauen unser Telefonbuch abermals neu ;)
      _____9.4 Fazit

      Änderungen und streichungen des Inhaltsverzeichnis bzw. Teile davon vorbehalten

      Für Fragen, Anregungne, Kritik, Lob oder Diskussionen gibt es den Supportthread für dieses Tutorial !!
      Antworten hier werden von den Mods in der Supportthread verschoben.
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 15 mal editiert, zuletzt von „Nofear23m“ ()

      1.0 Vorstellung

      1.0

      Vorstellung




      Mein Name ist Patschka Sascha-Heinz, ich bin 1983 geboren und arbeite als EDV Techniker. Beruflich habe ich fast nichts mit der Programmierung zu tun und komme sohin nur privat dazu mich sowohl weiterzubilden als auch mehr Übung zu bekommen.
      Da ich fast von Anfang an unter WPF programmiere und unter WinForms wirklich nur ca. 2-3 Monate gearbeitet habe gab es für mich von Anfang an nur die Richtung zur WPF. Die WPF ist ein sehr leistungsstarkes Framework welches einem nicht nur in Punkto Optik neue Möglichkeiten eröffnet.

      Anfangs hatte ich keine Ahnung von Pattern wie dem MVVM oder anderen, da ich das meiste einfach per "lerning by doing" gelernt habe. Erst nach einigen Jahren aktiver Programmierung unter WPF kam ich zu dem Pattern MVVM. Erstmals totales Neuland mit vielen verschiedenen Ansätzen und Anfangs schwer zu durchschauen, dachte ich mir nicht das dieses Pattern mich irgendwann dazu bringen könnte eine Aussage wie "wenn möglich verwende ich nur noch MVVM in der WPF" zu tätigen, doch seit einiger Zeit ist dies immer öfter der Fall.

      Ich kann sehr gut nachvollziehen wie frustrierend es sein kann mit der WPF zu arbeiten wenn man bereits längere Zeit mit z.B. WinForms gearbeitet hat. Es kann(!) sehr frustrierend sein wenn man nicht auf Anhieb weiterkommt und im Netz finden sich sowohl was die WPF Ansicht und deren Verwendung angeht viele verschiedene Ansätze also auch was das MVVM angeht. Das kann sehr frustrierend sein. Einige davon mehr oder weniger gut und manche leider auch sehr schlecht und gar nicht skalierbar. Ich selbst habe bereits sicher 20 verschiedene Ansätze der Umsetzung eines mehr oder weniger korrekten MVVM Patterns gesehen. Weiteres über MVVM in einem späteren Kapitel.

      Grüße
      Sascha

      Dateien
      • 1.0.pdf

        (290 kB, 82 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()

      1.1 Einleitung

      1.1

      Einleitung




      Ich werde absichtlich so wenig wie nur möglich mit Fremdwörtern oder kompliziertem Code um mich werfen. Es soll in dieser Tutorialreihe darum gehen den Code zu verstehen.
      Auch Anfänger sollten den Code lesen und nachbauen können. Evtl. wird auch Code auskommentiert werden und darunter eine andere Möglichkeit geboten wie z.B. eine Schleife gegen eine Lambda Expression vereinfacht werden kann, einfach damit auch Personen welche noch nicht mit Lambda gearbeitet haben verstehen was hier passiert.

      Einige Dinge werden in den Folgekapiteln sicher einfacher gehen oder besser gelöst werden können, hierfür steht der Diskussionsthread zur Verfügung stehen. Auch werde ich nur die wichtigsten Zeilen kommentieren damit bei Anfängern der Lerneffekt nicht ausbleibt. Ich werde in VisualStudio 2017 Update 3 schreiben und die .Net Sprache VB.NET verwenden.
      Falls Ihr Fragen zu diesem Tutorial, den Code oder über mich habt freue ich mich über ein Mail oder eine PM von euch. Auch für Kritik bin ich natürlich immer offen. Mails bitte über die Forumsfunktion über mein Profil oder eine PM hier im Forum bzw. im Supportthread. Ich setze in dieser Tutorialreihe Kenntnisse in der objektorientierten Programmierung voraus und gehe davon aus das die Grundkenntnisse und Syntax von VB.Net soweit bekannt sind.

      1.2

      Aufbau dieser Tutorialreihe



      Es wird ca. 1-mal pro Woche ein Beitrag mit mindestens einem Kapitel hier online gestellt. Es kann vorkommen das auch mal 2 oder mehr Kapitel behandelt werden. Je nachdem wie ich dazu komme und Zeit habe. Falls es vorkommen sollte das ich mal eine Woche auslasse entschuldige ich mich bereits im Voraus dafür, bitte habt Verständnis das ich mal in Urlaub fahre oder beruflich etwas mehr Stress habe.
      Diese Tutorialreihe wird als "Hybrid" aufgebaut. Teile werden als normale Beiträge in reinem Text bzw. mit Bildern erstellt, andere Teile aber auch als Videocast.
      Es wird außerdem für jedes Kapitel ein ZIP File bzw. PDF online gestellt welches das Inhaltsverzeichnis und die Kapitel bis zum aktuellen Zeitpunkt enthält. Außerdem mit in dem ZIP File wenn vorhanden die VisualStudio Solution abwärtskompatibel bis Visual Studio 2015, sowie Links zu den Videos sofern vorhanden.
      Sollte ein Beitrag rein als Text ohne Video erstellt worden sein wird ein PDF mit in der ZIP enthalten sein damit jeder auch offline in Ruhe alles lesen kann.

      Sämtliche Verweise in den Solutions werden nur als NuGet Verweise in das jeweilige Projekt eingebunden um sicherzustellen das die Solution nach dem Download auch bei jedem läuft da NuGet automatisch nachgeladen wird wenn nicht vorhanden. Weitere Infos könnt Ihr hier nachlesen. Warum mit Videos? Man könnte jetzt sagen das ist totaler Quatsch und aus einem Video kann ich nichts rauskopieren und ich kann schwer später gezielt zu einem bestimmten Code springen um mir diesen nochmals anzusehen.
      Aber genau das sollte auch vermieden werden. Ich bin kein Freund von Copy&Paste. Nur wenn ich den Code tippe kann ich versuchen ihn zu lernen und zu verstehen. Auch bin ich der Meinung dass über ein Video viel mehr über die Funktionalität von der IntelliSense vermittelt werden kann. Außerdem kann ich in einem Video schöner gewisse Tastenkombinationen und Tricks vermitteln welche einem das tägliche Leben leichter machen oder einem viel Tipparbeit ersparen wie z.B. bei CodeSnippets.

      Das sind alles Gründe warum ich persönlich ein Video einem normalen Text/Bild Beitrag vorziehe. Bitte entschuldigt wenn ich in meinem Video evtl. mal in meinen österreichischen Dialekt falle. Ich werde mich bemühen so gut wie möglich in einem verständlichen Hochdeutsch zu sprechen.

      Grüße
      Sascha
      Dateien
      • 2.0.pdf

        (476,09 kB, 43 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Nofear23m“ ()

      2.0 Grundlagen der WPF

      2.0

      Grundlagen der WPF




      Wir kommen zu den Grundlagen. Die WPF bietet eine eigene "Deisgnersprache". XAML (Extensible Application Markup Language); ist eine Markupsprache und ist ähnlich im Aufbau wie XML.
      Der Großteil der Benutzeroberfläche wird in der WPF mit XAML erstellt.

      Was ist XAML?
      Im Grunde vereinfacht XAML das Erstellen einer UI einer .NET Anwendung. Es können sichtbare UI-Elemente im deklarativen XAML-Markup erstellt und anschließend die UI-definition mithilfe von Code-Behind, die über partielle Klassendefinitionen an das Markup geknüpft sind, von der Laufzeitlogik trennen.
      Die Darstellung passiert als Text über XML Dateien welche die Erweiterung .xaml aufweisen. Es kann mit jeder Codierung gearbeitet werden, typisch ist jedoch die Codierung als UTF-8.

      Ich drifte aber zu weit ab, hier ein Beispiel für einen XAML - Code:

      VB.NET-Quellcode

      1. <Window xml:Class="MainWindow"
      2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      4. Title="Window with Button"
      5. Width="250" Height="100">
      6. <!-- Button hinzufügen -->
      7. <Button Name="button">Klick mich!</Button>
      8. </Window>


      Hier werden ein Fenster und eine Schaltfläche mithilfe der Elemente Window und Button definiert. Jedes Element wird mit Attributen konfiguriert und korrespondiert mit den jeweiligen Properties des Elements. Zeile zwei und drei beinhalten die per Default eingetragenen XAML Namespaces, dazu kommen wir auch später mal, da möchte ich im Moment nicht so weit vorgreifen. Ein Window hat ein Property Title und kann hier mit dem Attribut Title geändert werden.
      Geben wir also für den Button beim Attribut 'Name' den Wert 'button' an wird dieser Wert in das Property 'Name' geschrieben. In diesem Fall handelt es sich um ein Dependency Property aber dazu kommen wir mal in einem der Videos zu sprechen.

      So würde dieser Code im Programm aussehen:



      Unter Windows 7 so:



      Im Hintergrund passiert nichts anderes als das die WPF die Objekte anhand Ihrer Attribute und deren Werten erstellt.
      Erstellen wir dieses Fenster mal im Code:

      VB.NET-Quellcode

      1. Dim MainWindow As New Window
      2. MainWindow.Title = "Window with Button"
      3. MainWindow.Width = 250
      4. MainWindow.Height = 100
      5. Dim myButton As New Button
      6. myButton.Name = "button"
      7. myButton.Content = "Klick mich!"
      8. AddHandler myButton.Click, AddressOf Button_Click
      9. MainWindow.Content = myButton


      Wenn wir nun den XAML mit dem Code vergleichen fällt uns ziemlich schnell auf wie die WPF das macht.
      In einem <Button/> wird z.B. Dim myButton As New Button erstellt.
      Jedes Attribut steht für ein Property der jeweiligen Klasse.
      z.B. wird myButton.Name = "button" in XAML zu Name="button"

      Wenn man diese Info hat wird man die XAML Syntax gleich viel schneller verstehen.

      Code Behind

      Ich lese immer wieder in Foren das kein Code Behind verwendet werden soll und das man unter WPF nur MVVM verwenden soll, alles andere wäre Quatsch.
      Doch das ist nicht korrekt, auch in Code von Microsoft und diversen großen Herstellern wie DevExpress, welcher einer der größten Komponentenhersteller im .Net Bereich ist, wird immer wieder über Code Behind gearbeitet. Zweifels ohne ist die WPF auf Binding und gewisse Pattern ausgerichtet wodurch man gewisse Vorteile erlangt wenn man diese verwendet.

      Dennoch ist es so dass ich für eine kleinere Anwendung kein MVVM empfehlen würde. Näheres in einem späteren Kapitel.
      Ähnlich wie bei WinForms kann ich nun einen Handler für den Button_Click erzeugen und in diesem meinen Code schreiben. Wir schreiben das Attribut 'Click' in den Button XAML Code und drücken zweimal Tab.Nun wird folgende Codezeile als Button vorhanden sein:

      XML-Quellcode

      1. <Button Name="button" Click="button_Click_1">Klick mich!</Button>


      Visual Studio hat uns nun den Code in der Code Behind des Windows erstellt.
      Mit einem Rechtsklick auf den Code des Click Attributes können wir nun mit "Gehe zu Definition" direkt zu diesem Code springen.

      Hier steht nun folgendes:

      VB.NET-Quellcode

      1. Private Sub button_Click_1(sender As Object, e As RoutedEventArgs)
      2. End Sub


      Und dies kennen wir nun ja wieder aus WinForms.
      Was anders ist, ist der RoutedEventArg, dies erkläre ich allerdings im Kapitel RoutedEvents, da möchte ich jetzt noch nicht vorgreifen.

      Ein weiteres Beispiel mit Attributen:

      XML-Quellcode

      1. <Button Background="Blue" Foreground="Red" Content="This is a button"/>


      Es wird die Schriftfarbe des Controls auf die Farbe "Red" gesetzt und der Hintergrund des Controls auf "Blue".

      Allerdings gibt es auch Eigenschaften eines Objekts welche nicht über die Attributsyntax gesetzt werden da diese z.B. zu komplex sind. Auf diese kann dann über die Eigenschaftenelementsyntax zugegriffen werden.
      Oft ist es aber auch Geschmacksache oder Übersichtlichkeit für welche Art man sich entscheidet.
      Hier ein Beispiel für das umgestalten des oben stehenden Codes unter Verwendung der Eigenschaftenelementsyntax:

      XML-Quellcode

      1. <Button>
      2. <Button.Background>
      3. <SolidColorBrush Color="Blue"/>
      4. </Button.Background>
      5. <Button.Foreground>
      6. <SolidColorBrush Color="Red"/>
      7. </Button.Foreground>
      8. <Button.Content>
      9. This is a button
      10. </Button.Content>
      11. </Button>


      Dies wäre nun derselbe Button nur das die Properties über die Eigenschaftenelementsyntax gesetzt wurden.
      Jetzt könnte man sich denken: "Wozu gibt es denn die Eigenschaftenelementsyntax wenn ich das mit der Attributsyntax ja auch machen kann?" Hierfür gibt es mehrere Gründe. Einer wäre z.B. dass die Background Eigenschaft eines Buttons ja eigentlich einen Brush erwartet. Warum kann man dann Background="Blue" anwenden? Die WPF stellt intern diverse TypeConverter bereit, so kann sie den String "Red" in einen SolidColorBrush mit der Color "Red" umwandeln. Das gleiche gilt für die Eigenschaft Content des Buttons welche von Typ „Object“ ist.
      Hier macht die WPF automatisch einen String daraus.
      Aber warum soll ich die lange Variante schreiben wenn ich die kurze doch auch schreiben könnte?

      In diesem Fall (SolidColorBrush) geht das noch alles über die Attributsyntax da die WPF den String ja in einen SolidColorBrush wandelt.
      Wenn man nun einen Farbverlauf als Hintergrund verwenden möchte muss man aber schon auf die Eigenschaftenelementsyntax zurückgreifen. z.B.:

      XML-Quellcode

      1. <Button>
      2. <Button.Background>
      3. <LinearGradientBrush>
      4. <LinearGradientBrush.GradientStops>
      5. <GradientStop Offset="0.0" Color="Red" />
      6. <GradientStop Offset="1.0" Color="Blue" />
      7. </LinearGradientBrush.GradientStops>
      8. </LinearGradientBrush>
      9. </Button.Background>
      10. <Button.Foreground>
      11. <SolidColorBrush Color="Red"/>
      12. </Button.Foreground>
      13. <Button.Content>
      14. This is a button
      15. </Button.Content>
      16. </Button>


      Hier wird beim ersten Button für die Hintergrundfarbe ein Farbverlauf gewählt.
      Dieser Farbverlauf geht von oben nach unten von Rot nach Blau. Und zwar gleichmäßig.
      Über das Offset könnte man hier Einfluss auf die "Geschwindigkeit" des Verlaufs nehmen.

      Gehen wir gleich zu den XAML Inhaltseigenschaften.
      Diese sind auch ganz interessant. In der WPF gibt es viele Controls welche ein Property Content oder Child enthalten.
      Oft sind diese Properties vom Typ Object. Da ein Object übergeben werden kann, kann dies im Grunde alles mögliche sein. Nehmen wir wieder als Beispiel den guten alten Button.
      Die folgenden Buttons sehen alle völlig gleich aus obwohl man dies auf den ersten Blick vielleicht nicht vermuten mag.

      XML-Quellcode

      1. <StackPanel>
      2. <Button>Test</Button>
      3. <Button>
      4. <Button.Content>
      5. Test
      6. </Button.Content>
      7. </Button>
      8. <Button Content="Test"/>
      9. <Button>
      10. <TextBlock Text="Test"/>
      11. </Button>
      12. <Button>
      13. <Button.Content>
      14. <TextBlock>
      15. <TextBlock.Text>
      16. Test
      17. </TextBlock.Text>
      18. </TextBlock>
      19. </Button.Content>
      20. </Button>
      21. </StackPanel>


      Hier ein Screenshot:


      XML-Quellcode

      1. <Border BorderThickness="2" BorderBrush="Blue" Margin="10">
      2. <StackPanel>
      3. <UniformGrid Columns="2">
      4. <TextBlock HorizontalAlignment="Center">Text1</TextBlock>
      5. <TextBlock HorizontalAlignment="Center"
      6. Grid.Column="1">Text2</TextBlock>
      7. </UniformGrid>
      8. <Button>
      9. <StackPanel Orientation="Horizontal">
      10. <Image Width="100"
      11. Source="http://www.vb-paradise.de/wcf/images/wbbLogo_vbp.png"/>
      12. <TextBlock Text="Gehe online" Margin="20,0,0,0"/>
      13. </StackPanel>
      14. </Button>
      15. </StackPanel>
      16. </Border>


      Hier wieder ein Screenshot:


      Ich denke das war jetzt erstmal genug Theorie, ich finde das man mit "lerning by doing" einfacher das gelernte behält. Sicher ist es gut wenn man weiß wie die Syntax aufgebaut ist, man muss aber auch damit umgehen können. Die wichtigsten Grundlagen der Syntax habe ich ja aufgezeigt, ich würde sagen wir legen jetzt bald mal los. Beim "basteln" der ersten Anwendung werden sicher viele Fragen bereits beantwortet. Ich werde auch versuchen meine Schritte immer zu kommentieren und euch hin und wieder verschiedene Wege zu zeigen um ans Ziel zu kommen.

      Weitere Grundlagen und Infos findet Ihr hier: Gut in verschiedene Kategorien unterteilt und mit vielen Beispielen. Habe diese Pages damals mehrfach gelesen.

      Ich werde in den nächsten Kapiteln eine Applikation mit reinem Code Behind erstellen und absichtlich auch aufzeigen das man auch ohne Binding in der WPF zurechtkommt, allerdings ist der Komfort nicht gegeben welchen die WPF eigentlich bietet.
      Es soll jetzt niemanden Animieren kein Binding zu verwenden, ich möchte nur aufzeigen das auch dies möglich ist und mich langsam an das Binding herantasten.
      So denke ich, kann man besser umdenken und verstehen wie das Binding funktioniert wenn man beide Wege kennt und parallelen ziehen kann.

      Fragen, Diskussionen, Lob und Kritik wieder im Supportthread!


      Im nächsten Kapitel werde ich das erste Video hochladen. Bis dann Leute :thumbup:
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Nofear23m“ ()

      Einführung in die WPF

      2.1

      Einführung in die WPF


      In diesem Kapitel werden wir ein paar Beispiele durchgehen. Das Hauptaugenmerk wird hier auf XAML gelegt. Wir werden die wichtigsten Controls kennenlernen, wie wir diese Anwenden und auch untereinander kombinieren können um somit ein völlig neues Aussehen und zum Teil neues Verhalten über Trigger und Animations in das Control bekommen. Außerdem werden wir lernen wie wir ein Fenster so gestallten das dieses völlig dynamisch auf Größenänderungen reagiert.

      Dabei werden die Grundlagen von DataBinding in der WPF durchgehen, erst anhand von Bindings innerhalb des Views wie Beispielsweise wie ich ein Property eines Controls auf ein Property eines anderen Controls Binden kann wo wir auch Converter kennenlernen werden aber auch mit Binding an eine selbst geschrieben Klasse bis zum Designtime-Support.


      Dieses Kapitel wird bereits einige Videos enthalten da in einem Video einfach besser Dinge wie Intellisense zur Geltung kommen. Bitte verzeiht mit nochmals wenn ich anfangs vielleicht nicht so geübt rüberkomme.

      2.1.1
      Die wichtigsten Controls und deren Verwendung (Video)



      Wir erstellen ein WPF Projekt und schreiben XAML, wobei wir aber aus gutem Grund auf Drag&Drop in den Designer verzichten werden, warum erkläre ich im Video.
      Wir lernen die wichtigsten Controls kennen und spielen damit dass sich diese an die Fenstergröße anpassen.

      Vorweg: Ich hatte als ich das Video letzte Woche aufnahm noch ein anderes Inhaltsverzeichnis. Bitte verzeiht mir das ich in der Powerpoint noch eine alte Kapitelnummer stehen habe.
      Ich werde mich bemühen solche Fehler in Zukunft zu unterlassen.





      Bitte nutzt für Fragen, Kritik und Lob wieder den SupportThread da dies ein Inkrementelles Tutorial ist!
      Dateien
      • 2.0.pdf

        (737,21 kB, 63 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()

      2.1.1.2 - Styles

      2.1.1.2

      Styles, Templates und Trigger. Heute: Styles




      Wir lernen Styles kennen und sehen uns an was es damit auf sich hat.
      Oft soll die Darstellung von Elementen desselben Typs innerhalb einer UI identisch sein. Wie im Web das CSS gibt es in der WPF hierfür Styles. Die Wiederverwendung von Stilen (Styles) erleichtert das Entwickeln und die Wartung eines UI.

      Hier ein Beispiel für einen Style:

      XML-Quellcode

      1. <Style TargetType="{x:Type Button}">
      2. <Setter Property="VerticalContentAlignment" Value="Top" />
      3. <Setter Property="HorizontalContentAlignment" Value="Right" />
      4. <Setter Property="FontWeight" Value="Bold" />
      5. <Setter Property="Margin" Value="0,0,0,5" />
      6. <Setter Property="Background" Value="Aqua"/>
      7. </Style>


      Styles können in XAML mit einem Key versehen oder über den Typ definiert werden. Gibt man einen Key an so kann man bei jedem Steuerelement über das „Style“ Attribut den Style als StaticResource bzw. DynamicResource angegeben.

      XML-Quellcode

      1. <Window.Resources>
      2. <Style x:Key="myButtonStyle" TargetType="{x:Type Button}">
      3. <Setter Property="VerticalContentAlignment" Value="Top" />
      4. <Setter Property="HorizontalContentAlignment" Value="Right" />
      5. <Setter Property="FontWeight" Value="Bold" />
      6. <Setter Property="Margin" Value="0,0,0,5" />
      7. <Setter Property="Background" Value="Aqua"/>
      8. </Style>
      9. </Window.Resources>
      10. <Grid>
      11. <Button Content="Testbutton" Style="{StaticResource myButtonStyle}"/>
      12. </Grid>


      Styles welchen ein „TargetType“ angegeben wird greifen auf jedes Steuerelement dieses Typs unterhalb der Hierarchie. Gibt man in den Window-Resourcen einen Style mit dem TargetType „Button“ an, greift dieser Style auf jeden Button innerhalb dieses Fensters. Auch wenn sich das Steuerelement in einem UserControl befindet welches sich im Fenster befindet greift das Style auf Buttons innerhalb des UserControls. Stichwort: Vererbung.
      Allerdings können jederzeit einzelne Setter eines Styles überschrieben werden. Wenn ein Style die Hintergrundfarbe von Buttons auf BLAU festlegt sind alle Buttons blau. Möchte ich das für einen Button explizit ändern ohne auf das Style für alle anderen Buttons verzichten zu müssen kann ich bei diesem Button einfach mit Background="Green" diesen einen Setter des Style überschreiben, die anderen Setter bleiben allerdings uneingeschränkt vorhanden.

      Auch für Styles habe ich wieder ein Video für euch. 8o



      Viel Spaß mit dem Video, gerne könnt ihr mir ein Like und/oder ein Kommentar hinterlassen und wieder den SupportThread verwenden um Fragen zu stellen.
      Bis zum nächsten Video

      Liebe Grüße
      Sascha
      Dateien
      • 2.1.1.2.pdf

        (770,53 kB, 23 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      2.1.1.2 - Templates

      2.1.1.2

      Styles, Templates und Trigger. Heute: Templates




      Bei Template müssen wir zunächst mal zwischen ControlTemplates, DataTemplates, ItemsPanelTemplates und HirachicalDataTemplates unterscheiden. Es ist erstmal wichtig zu wissen welche Art von Template man gerade benötigt um die aktuelle Aufgabenstellung meistern zu können. Nur wenn man weiß was für ein Template man gerade benötigt wird man über die Suchmaschine seiner Wahl auch korrekte Ergebnisse bekommen und erspart sich erstmal die Suche nach dem richtigen Begriff.

      Fangen wir mit den ControlTemplates an.

      Generell sind Steuerelemente in der WPF mit einer gewissen Logik versehen welche States, Styles, Events, Properties und ein Template beinhalten welche das Aussehen des Steuerelements wie z.b. einen Button definieren/steuern.Die Verbindung zwischen dieser Logik und dem Template passiert über Binding. Jedes Steuerelement besitzt ein Standard – Template welches für jede Windows-Version mitgeliefert wird. Unter Windows 7 sieht ein Button Beispielsweise anders aus als unter Windows 8/10.
      Dieses Template ist verpackt in einem Style, dem DefaultStyleKey und kann überschrieben werden. Diesen Style besitzt jedes UI Steuerelement. Ein Template ist definiert über ein Dependency Property mit dem Namen Template. Durch setzen dieses Property kann das Aussehen eines Steuerelementes völlig neu übernommen werden.

      Hier eine sehr gute Grafik von wpftutorials.net:

      Diese Grafik erklärt sehr gut wie ein solches einfaches Template aufgebaut ist und wie es auf Eigenschaftenänderung reagiert. Siehe Properties IsFocused oder IsEnabled.

      Sehen wir uns eine einfache Überschreibung eines Templates anhand eines Buttons an:

      XML-Quellcode

      1. <Style x:Key="MyButtonStyle" TargetType="Button">
      2. <Setter Property="Template">
      3. <Setter.Value>
      4. <ControlTemplate TargetType="{x:Type Button}">
      5. <Grid>
      6. <Path Data="M 0,0 A 100,100 90 0 0 100,100 L 100,100 100,0" Fill="{TemplateBinding Background}"
      7. Stroke="{TemplateBinding BorderBrush}"/>
      8. <ContentPresenter HorizontalAlignment="Center"
      9. VerticalAlignment="Center"/>
      10. </Grid>
      11. </ControlTemplate>
      12. </Setter.Value>
      13. </Setter>
      14. </Style>




      Hier wird ein ganz einfacher Button erstellt. Dieser besitzt weder Hover noch andere Styleelemente welche einen Button auszeichnen. Beispielsweise möchten wir ja wenn wir den Button klicken, dass dieser richtig hineingedrückt wird. Wenn ein Button „Disabled“ ist soll er ausgegraut sein. All diese Funktionalitäten Fehlen hier.

      Im folgenden Video sprechen wir nun darüber wie wir dies bewerkstelligen.
      Außerdem zeige ich euch wie ihr das Default-Template eines jeden Controls erfahren und anpassen könnt. Dies ist insofern Praktisch, wenn Ihr ein anderes Verhalten eines Buttons bewerkstelligen wollt, ohne ein neues Control erstellen zu müssen.

      Nun zu den DataTemplates

      DataTemplates helfen und dabei gewisse Daten oder Klassen so darzustellen wie wir das möchten. Beispielsweise Binden wir eine Property welche Autos beinhaltet an eine ListBox.Autos enthält viele Instanzen von der Klasse Auto. Die ListBox versucht nun mit den Daten etwas anzufangen und sucht nach einem DataTemplate. Erst bei sich selbst, dann in den Resourcen von darüber liegenden Controls, bis in der Hierarchie nichts mehr vorhanden ist, dann sucht sie in der Application.xaml nach einem DataTemplate.

      Nehmen wird eine einfache Klasse,- sagen wir mal diese soll ein Auto enthalten.
      Also erstellen wir uns eine Klasse „Auto“.

      VB.NET-Quellcode

      1. Public Class Auto
      2. Public Sub New()
      3. End Sub
      4. Public Sub New(marke As String, modell As String, ps As Integer)
      5. Me.Marke = marke : Me.Modell = modell : Me.PS = ps
      6. End Sub
      7. Public Sub New(marke As String, modell As String, ps As Integer, logo As Uri)
      8. Me.Marke = marke : Me.Modell = modell : Me.PS = ps : Me.Logo = logo
      9. End Sub
      10. Public Property Marke As String
      11. Public Property Modell As String
      12. Public Property PS As Integer
      13. Public Property Logo As String
      14. End Class


      In der CodeBehind des MainWindow sorgen wird jetzt einfach dafür das eine ObservableCollection (Auflistung) mit verschiedenen Auto`s befüllt wird.

      VB.NET-Quellcode

      1. Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
      2. AutoListe = New ObservableCollection(Of Auto)
      3. With AutoListe
      4. .Add(New Auto("Audi", "R8 V10+", 610, "BrandImages/Audi.png"))
      5. .Add(New Auto("VW", "Arteon TDI 4 Motion", 240, "BrandImages/Vw.png"))
      6. .Add(New Auto("Seat", "Leon ST Cupra TSI DSG", 300, "BrandImages/SEAT.png"))
      7. .Add(New Auto("Skoda", "Octavia RS", 230, "BrandImages/Skoda.png"))
      8. .Add(New Auto("Lamborghini", "Aventador LP 700", 700, "BrandImages/Lambo.png"))
      9. .Add(New Auto("Bentley", "Continental Supersports", 630, "BrandImages/Bentley.png"))
      10. End With
      11. Me.DataContext = Me
      12. End Sub
      13. Public Property AutoListe As ObservableCollection(Of Auto)


      Im View (MainWindows.xaml) müssen wir nun nur noch eine ListBox erstellen und diese auf das Property „AutoListe“ binden. Fertig.
      Aber was sehen wir nun genau?

      Hier eine ListBox gebunden an Autos ohne DataTemplate:


      Nicht so schön. Wieder schlägt der TypeConverter der WPF zu.
      Die WPF wirft keinen Fehler sondern versucht die Daten welche ihr (ist die WPF ne Frau?) übergeben werden einfach irgendwie zu Rendern. Was liegt näher als .ToString aufzurufen. Und genau das macht sie.

      Wir könnten nun die ToString-Methode in der Klasse „Auto“ überschreiben um einen „verständlichen“ Text in die ListBox zu bekommen.

      VB.NET-Quellcode

      1. Public Overrides Function ToString() As String
      2. Return $"Marke: {Marke }, Modell: {Modell } Leistung: {PS }"
      3. End Function


      Was uns folgendes Ergebnis liefert:


      OK, schon um einiges besser, aber lange noch nicht zufriedenstellend. Wir befinden uns in der WPF, das geht ja mal sicher viel besser und schöner oder?
      Richtig. Mittels DataTemplate kann man nun bestimmen wie das Template für ein ListItem aussehen soll. Template = Vorlage. Also erstellen wir eine Vorlage und geben der WPF die Info für was (die Klasse Auto) dieses Template verwendet werden soll.

      Hier ein DataTemplate direkt in das ItemTemplate der ListBox:

      XML-Quellcode

      1. <ListBox ItemsSource="{Binding AutoListe}" Margin="10">
      2. <ListBox.ItemTemplate>
      3. <DataTemplate>
      4. <Grid>
      5. <Grid.ColumnDefinitions>
      6. <ColumnDefinition Width="60"/>
      7. <ColumnDefinition Width="*"/>
      8. </Grid.ColumnDefinitions>
      9. <Border Margin="5" BorderBrush="Black" BorderThickness="1">
      10. <Image Source="{Binding Logo}" Stretch="Uniform" Width="50" Height="50" RenderOptions.BitmapScalingMode="HighQuality" />
      11. </Border>
      12. <StackPanel Grid.Column="1" Margin="5">
      13. <StackPanel Orientation="Horizontal">
      14. <TextBlock Text="{Binding Path=Marke}" />
      15. <TextBlock Text="{Binding Path=Modell}" Padding="3,0,0,0"/>
      16. </StackPanel>
      17. <TextBlock FontWeight="Bold" >
      18. <Run Text="{Binding PS,FallbackValue=0}"/>
      19. <Run Text=" PS"/>
      20. </TextBlock>
      21. </StackPanel>
      22. </Grid>
      23. </DataTemplate>
      24. </ListBox.ItemTemplate>
      25. </ListBox>


      Dieses DataTemplate ändert nun das Aussehen eines ListBox-Items wie folgt:



      Mehr im Video weiter unten, aber jetzt gehen wir mal weiter zu dem ItemsPanelTemplates:

      ItemsPanelTemplates

      Diese Art von Templates erlaubt es uns das Layout, wie Items eines ItemControls wie z.b. einer ListBox zu bestimmen. Jeder ItemsControl besitzt von Haus aus ein „Default Panel“.

      Die ListBox z.b. besitzt von Haus aus ein VirtualizingStackPanel als PanelTemplate.
      Dieses ist im Grunde ein normales StackPanel welches ein Zusatzfeature besitzt, welches ermöglicht das nicht alle Elemente sofort gerendert werden sondern erst dann wenn diese z.b. durch Scrollen auftauchen was Resourcen spart und stark auffällt wenn man mehrere tausend Items in der Liste hat.

      Um dieses Template nun zu überschreiben, erstellen wir einfach ein ItemsPanelTemplate und suchen uns ein Panel-Control aus welches uns besser passt.

      XML-Quellcode

      1. <ListBox ItemsSource="{Binding AutoListe}">
      2. <ListBox.ItemsPanel>
      3. <ItemsPanelTemplate>
      4. <UniformGrid Columns="4"/>
      5. </ItemsPanelTemplate>
      6. </ListBox.ItemsPanel>
      7. </ListBox>


      In diesem Fall nehmen wir jetzt mal ein UniformGrid mit vier Spalten. Dieses UniformGrid wird nun die Items auf vier Spalten aufteilen. Das fünfte Element würde dann in eine neue Zeile verschoben werden.

      Mit dem Codeschnipsel von oben würde nun folgendes generiert werden:


      Wir können sehen das wir vier Spalten und zwei Zeilen haben. Wieder hat die WPF unsere .ToString Methode in der Klasse Auto aufgerufen.
      Aber das wir DataTemplates oben bereits durchgenommen haben ist es für uns ja jetzt ein leichtes ein solches DataTemplate abermals zu implementieren.
      Wir können gleich unser DataTemplate von oben auch in dieser ListBox verwenden, mit dem Unterschied das wir das soeben erstellte ItemsPanelTemplate auch mit in der ListBox behalten:

      XML-Quellcode

      1. <ListBox ItemsSource="{Binding AutoListe}">
      2. <ListBox.ItemsPanel>
      3. <ItemsPanelTemplate>
      4. <UniformGrid Columns="4"/>
      5. </ItemsPanelTemplate>
      6. </ListBox.ItemsPanel>
      7. <ListBox.ItemTemplate>
      8. <DataTemplate>
      9. <Grid>
      10. <Grid.ColumnDefinitions>
      11. <ColumnDefinition Width="60"/>
      12. <ColumnDefinition Width="*"/>
      13. </Grid.ColumnDefinitions>
      14. <Border Margin="5" BorderBrush="Black" BorderThickness="1">
      15. <Image Source="{Binding Logo}" Stretch="Uniform" Width="50" Height="50" RenderOptions.BitmapScalingMode="HighQuality" />
      16. </Border>
      17. <StackPanel Grid.Column="1" Margin="5">
      18. <StackPanel Orientation="Horizontal">
      19. <TextBlock Text="{Binding Path=Marke}" />
      20. <TextBlock Text="{Binding Path=Modell}" Padding="3,0,0,0"/>
      21. </StackPanel>
      22. <TextBlock FontWeight="Bold" >
      23. <Run Text="{Binding PS,FallbackValue=0}"/>
      24. <Run Text=" PS"/>
      25. </TextBlock>
      26. </StackPanel>
      27. </Grid>
      28. </DataTemplate>
      29. </ListBox.ItemTemplate>
      30. </ListBox>


      Hierdurch erhalten wir wieder die Optik unseres Items aber in der Anordnung wie wir es im ItemsPanelTemplate vorgegeben hatten:


      Wir sehen, alle Elemente werden so gerendert wie wir das haben wollten und in dem Schema wie wir dies vorgegeben haben. So eröffnen sich tolle möglichkeiten für eine neue Anwendungsoptik und eine bessere und flexiblere Benutzerführung.
      Langsam dürfte wiedermal ein kleiner WOW-Effekt einsetzen was nun alles möglich ist mit ein paar Zeilen XAML ;)

      Last but not least, HierarchialDataTemplates

      Mit HierarchialDataTemplate wie der Name vermuten lässt kann ich bestimmen wie Daten welche in Form einer Hierarchie vorliegen darstellen.
      Tja, wo liegt nun der Einsatz von einem solchen Template? Z.b. bei der Verwendung eines TreeViews oder eines Menus.

      Wir alle kennen ein Menu:


      Erstmal haben wir die erste Ebene (Root) mit „Datei“, „Bearbeiten“, Ansicht“, usw.
      Danach haben wir eine Unbestimmte Anzahl an Ebenen welche wieder eine unbestimmte Anzahl an weiteren Kind-Ebenen haben kann.

      Auch für solch einen Fall hat die WPF vorgesorgt, und ermöglicht uns das Binding.
      Damit wir allerdings auch bestimmen können wie die Darstellung passiert gibt es eben die HierarchialDataTemplates. Besser darstellen lässt sich solch ein unterfangen mit einem TreeView.

      Als Fallbeispiel nehmen wir mal eine Art Stammbaum.
      Wie soll es anders sein nehme ich den Stammbaum der Familie Porsche/Piech:

      Erstmal erstelle ich zwei Klassen. Zum einen die Klasse „Parent“ und zum anderen die Klasse „Child“. Ich denke die Namen sprechen für sich.


      Jedes Parent kann X Childs (Kinder) haben. Jedoch kann jedes ChildElement wieder X Childs (Kinder) haben, usw. Füllen wir diese Klassen mit ein paar Daten von hier und konzentrieren wir uns wieder auf den XAML.
      Wir erstellen ein TreeView und geben ein HierarchialDataTemplate an:

      XML-Quellcode

      1. TreeView DataContext="{Binding}" ItemsSource="{Binding HierarchieDaten}">
      2. <TreeView.ItemTemplate>
      3. <HierarchicalDataTemplate ItemsSource="{Binding Kinder}">
      4. <StackPanel>
      5. <StackPanel Orientation="Horizontal">
      6. <Rectangle Width="10" Height="10" Fill="Red"/>
      7. <TextBlock Text="{Binding VollerName}"/>
      8. </StackPanel>
      9. <TextBlock>
      10. <Run Text="Gegr.: "/>
      11. <Run Text="{Binding GruenderVon}"/>
      12. </TextBlock>
      13. </StackPanel>
      14. </HierarchicalDataTemplate>
      15. </TreeView.ItemTemplate>
      16. </TreeView>


      Das sieht ja gar nicht so kompliziert aus. Das TreeView selbst haben wir an ein Property mit dem Namen „HierachieDaten“ gebunden. Dieses befindet sich in der CodeBehind und ist vom Typ Parent.
      Wie wir im Diagramm sehen konnten hat dieses ein Property Kinder. Dieses kann viele Child halten und Child wiederum auch viele Childs.

      Beim Erstellen des HierarchialDataTemplates geben wird für dieses dann als ItemsSource das Property an welches innerhalb der Elternklasse die Childs hält. Und der Rest ist einfach nur XAML welches bestimmt wie ein TreeViewItem dann für dieses Template aussehen soll.

      Folgende Ansicht wird in diesem Fall generiert:


      Soweit sieht das ja schon ganz gut aus. Wie wir aber sehen können hat nicht jedes Kind der Familie wieder etwas oder eine Marke gegründet. Da wir aber im Template hinterlegt haben das ein Item so gerendert werden soll wird uns der Text „Gegr.:“ angezeigt, da die Klasse Child allerdings kein solches Property besitzt kann die WPF gar nicht darauf Binden.

      Dies macht sich auch im Ausgabefenster bemerkbar:


      OK, wir wissen also das wir nicht am Holzweg sind, aber es hier noch Luft nach oben gibt, es muss ja möglich sein für jede Art von Element eine eigene Optik zu definieren.
      Naja, vorher hatten wir gerade noch die DataTemplates gelernt, das wäre doch eine Möglichkeit gleich das gelernte anhand dieses Beispiels zu versuchen.

      Wir müssen also ein wenig umdenken. Wir möchten mehrere HierarchialDataTemplates definieren, werden jedoch scheitern wenn wir versuchen noch ein Template darunter zu erstellen. Wir versuchen es in den Ressourcen:

      XML-Quellcode

      1. <TreeView DataContext="{Binding}" ItemsSource="{Binding HierarchieDaten}">
      2. <TreeView.Resources>
      3. <HierarchicalDataTemplate ItemsSource="{Binding Kinder}" DataType="{x:Type local:Parent}">
      4. <StackPanel>
      5. <StackPanel Orientation="Horizontal">
      6. <Rectangle Width="10" Height="10" Fill="Red"/>
      7. <TextBlock Text="{Binding VollerName}"/>
      8. </StackPanel>
      9. <TextBlock>
      10. <Run Text="Gegr.: "/>
      11. <Run Text="{Binding GruenderVon}"/>
      12. </TextBlock>
      13. </StackPanel>
      14. </HierarchicalDataTemplate>
      15. <HierarchicalDataTemplate ItemsSource="{Binding Kinder}" DataType="{x:Type local:Child}">
      16. <StackPanel Orientation="Horizontal">
      17. <Rectangle Width="10" Height="10" Fill="Blue"/>
      18. <TextBlock Text="{Binding VollerName}"/>
      19. </StackPanel>
      20. </HierarchicalDataTemplate>
      21. </TreeView.Resources>
      22. </TreeView>


      Wenn wir uns dieses TreeView ansehen werden wir die Stirn runzeln.
      Zwei Templates? JA, das erste Template dient zur Anzeige eines Parent-Objekts. Zu erkennen an der Angabe des DataType: DataType="{x:Type local:Parent}"
      Das zweite Template dient zur Anzeige des Child-Objekts: DataType="{x:Type local:Child}"
      Die WPF entscheidet nun anhand des Übergebenen Typs jedes Knotens wie dieser gerendert werden soll.

      Hier das Ergebnis:


      Man kann schön erkennen das beim Child-Knoten nicht nur das Quadrat in einer anderen Farbe erstrahlt sondern auch das hier der TextBlock mit „Gegr.:“ fehlt, da wir diesen TextBlock ins Child-Template nicht mit eingebaut haben.
      Eine schöne und saubere Sache.

      In folgendem Video gehe ich etwas näher darauf ein und zeige euch verschiedene Templates anhand von einigen Beispielen:



      Ich wünsche euch viel spass mit dem Video, bitte hinterlasst mir ein Like und/oder ein Kommentar, und verwendet für Fragen gerne den Supportthread.
      Anbei die Sulution und wieder das aktuellste PDF.


      Grüße und bis zum nächsten Tutorial.
      Sascha
      Dateien
      • WPF_Templates.zip

        (1,05 MB, 32 mal heruntergeladen, zuletzt: )
      • 2.1.1.2_#2.pdf

        (964,8 kB, 31 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()

      2.1.1.2

      Styles, Templates und Trigger. Heute: Trigger




      Auch bei Triggern müssen wir wieder unterscheiden da es hier mehrere Arten von Triggern gibt.
      Folgende Trigger gibt es:
      • Trigger
      • DataTrigger
      • Multitrigger
      • MultiDataTrigger
      • EventTrigger
      Trigger werden überwiegend in Styles oder ControlTemplates verwendet. Er Triggert ein Property auf ein anderes Property dieses Controls.
      Beispiel: Ein Trigger soll die Hintergrundfarbe des Buttons auf ROT setzen wenn das Property IsMouseOver True ist.

      XML-Quellcode

      1. <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
      2. <Style.Triggers>
      3. <Trigger Property="IsMouseOver" Value="True">
      4. <Setter Property="Background" Value="Red" />
      5. </Trigger>
      6. </Style.Triggers>
      7. </Style>


      Ein DataTrigger wird bei Datenbindung eingesetzt und wird überwiegend in DataTemplates verwendet. Beispielsweise kann ein DataTrigger verwendet werden um die Hintergrundfarbe eines Controls in ROT zu ändern wenn das Property Alert der Klasse True ist. DataTrigger können allerdings auch in ControlTemplates nützlich sein um einen roten Rahmen um ein Controls zu machen wenn in der Klasse Kontoinfo das Property Kontostand weniger als 0 Beträgt. Hierfür kann ein IValueConverter bestimmten das bei negativen Werten der Converter True zurückgibt und sohin der Rahmen Rot gezeichnet wird.

      XML-Quellcode

      1. <DataTrigger Binding="{Binding Alert}" Value="True">
      2. <Setter Property="Background" Value="Red"></Setter>
      3. </DataTrigger>


      MultiTrigger und MultiDataTrigger sind im Grunde dasselbe wie die beiden Triggerarten oben nur das mehrere Bedingungen angegeben werden können. Ein MultiDataTrigger würde dann nur greifen wenn alle Bedingungen erfüllt sind.

      XML-Quellcode

      1. <DataTemplate.Triggers>
      2. <MultiDataTrigger>
      3. <MultiDataTrigger.Conditions>
      4. <Condition Binding="{Binding Path=Picture}" Value="{x:Null}" />
      5. <Condition Binding="{Binding Path=Title}" Value="Waterfall" />
      6. </MultiDataTrigger.Conditions>
      7. <MultiDataTrigger.Setters>
      8. <Setter TargetName="viewImage" Property="Source" Value="/Images/noImage.png"/>
      9. <Setter TargetName="viewImage" Property="Opacity" Value="0.5" />
      10. <Setter TargetName="viewText" Property="Background" Value="Brown" />
      11. </MultiDataTrigger.Setters>
      12. </MultiDataTrigger>
      13. </DataTemplate.Triggers>


      EventTrigger schließlich sind Trigger welche auf ein Event reagieren können.
      Beispiel: Der Hintergrund eines Buttons soll sich ändern wenn sich die Maus über den Button fährt. EventTrigger werden Beispielsweise oft in Storyboards verwendet um z.b. eine Animation zu starten.

      XML-Quellcode

      1. <Border Name="border1" Width="100" Height="30"
      2. BorderBrush="Black" BorderThickness="1">
      3. <Border.Background>
      4. <SolidColorBrush x:Name="MyBorder" Color="LightBlue" />
      5. </Border.Background>
      6. <Border.Triggers>
      7. <EventTrigger RoutedEvent="Mouse.MouseEnter">
      8. <BeginStoryboard>
      9. <Storyboard>
      10. <ColorAnimation Duration="0:0:1"
      11. Storyboard.TargetName="MyBorder"
      12. Storyboard.TargetProperty="Color" To="Gray" />
      13. </Storyboard>
      14. </BeginStoryboard>
      15. </EventTrigger>
      16. </Border.Triggers>
      17. </Border>


      Da Animationen wiederum ein oder mehrere Kapiteln füllen würde, ich darauf aber nicht näher eingehen werde da ich der meinung bis das diese eigentlich relativ selten gebraucht werden, hier ein Link wo Ihr alle Wissenswertes über Animationen gut erklärt bekommt. WPF Basic Animations
      Wer sich hier durchklickt kommt bald zu den Easing Functions, zu den Key Frame Animations und schließlich zu den PathAnimations

      In folgendem Video zeige ich euch nun wie wir mit Triggern umgehen und wie wir das Verhalten von Controls beeinflussen können ohne viele, viele Codezeilen schreiben zu müssen. Selbst wenn wir Converter schreiben bestehen diese meist nur aus 1-5 Zeilen Code. Eine saubere und übersichtliche Sache.



      Viel Spaß mit dem Video, gerne könnt ihr mir ein Like und/oder ein Kommentar hinterlassen und wieder den SupportThread verwenden um Fragen zu stellen.
      Bis zum nächsten Video

      Liebe Grüße
      Sascha
      Dateien
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ () aus folgendem Grund: Anhänge eingefügt und Links korrigiert.

      2.1.1.3

      Controls eine neue Optik verpassen, inkl. deren Verhalten




      In den vorigen drei Kaptiteln haben wir erfahren wie wir mittels Styles, Triggern und Templates Controls anpassen. In jedem dieser Kapitel haben wir mehr oder weniger entweder das Aussehen oder das Verhalten eines Controls beeinflussen können. Nun ist es an der Reihe das erlernte wissen umzusetzen und ein Control komplett zu überarbeiten.

      Ich habe mir die Checkbox ausgesucht, einfach weil dies ein Control ist welchen von Haus aus nicht unbedingt sehr gut aussieht und meisst als erstes abgeändert werden möchte.
      Was wollen wir erreichen:

      Jeder kennt eine Checkbox:


      Diese ist nicht sonderlich schön. Ich dachte mir, wir machen eine Kopie des SwitchButton aus dem MobileOS Android:


      In folgendem Video erkläre ich euch wie Ihr eine Checkbox in genau dieser Optik erstellt. Ohne eine Zeile VB Code. Inkl. Animation des "Knopfes". Also das wenn die Checkbox ihren State ändert oder der User darauf klickt der Knopf nach links oder nach rechts "slidet".
      Wie Ihr euch sicher vorstellen könnt kann all dies über ein ControlTemplate erledigt werden.

      Viel spass mit dem Video:



      Für die die mit einem Video nicht viel anfangen habe ich natürlich wieder das Projekt angehängt.


      Viel Spaß mit dem Video, gerne könnt ihr mir ein Like und/oder ein Kommentar hinterlassen und wieder den SupportThread verwenden um Fragen zu stellen.
      Bis zum nächsten Video

      Liebe Grüße
      Sascha
      Dateien
      • 2.1.1.3_ControlOptik.zip

        (253,58 kB, 8 mal heruntergeladen, zuletzt: )
      • 2.1.1.3.pdf

        (997,96 kB, 24 mal heruntergeladen, zuletzt: )
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()