C# MVVM simple Lab

 

Visual Studio 2015 neues WPF Projekt anlegen. Ziel ist es eine WPF View mit dem MVVM Entwurfsmuster mit Logik zu verbinden.

image

Viewmodel Klasse erstellen

dem Projekt Klasse hinzufügen mit dem Namen StarterViewModel.cs. Dies stellt das Viewmodel dar. Die Klasse bekommt nun eine Property Zahl vom Standard Datentyp Int die per Getter und Setter gelesen oder geschrieben werden kann.

In der Klasse tippst du propfull [TAB] [TAB]. Per Tab durch die markierten Felder navigieren. Dabei die interne Variable zahl (klein) nennen und die externe Zahl (gross).

propfull

Um dem später erzeugten Objekt die Möglichkeit zu geben, das UI über Änderungen zu informieren wird das Interface INotifyPropertyChanged implementiert. Nach dem Klassennamen –getrennt durch einen Doppelpunkt –wird das Interface getippt. Visual Studio unterwellt den Namen rot. Das Property benötigt den Namensraum System.Componentmodel. Visual Studio schlägt per [STRG] + [.] die nötige using Direktive vor und inkludiert diese auf [RETURN].

image

Die  Codestelle INotifyPropertyChanged ist dann noch immer rot unterwellt, da das Interface ein konkrete Implementierung vorschreibt. Dies ist in diesem Fall das Event PropertyChangedEventHandler.

image

Es befindet sich nun folgende zusätzliche Zeile Code in der Klasse. Der Access Modifier ist Public um das Event außerhalb des Objektes nutzen zu können.

   1:   public event PropertyChangedEventHandler PropertyChanged;

In der Praxis wird das Event im Viewmodel gekapselt um eine leichtere und wiederverwendbare Handhabung zu haben. Folgende C# Code in die Viewmodel Klasse kopieren.

  protected void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

Im Setter der Property Zahl wird nach Zuweisung des internen Feldes zahl, das Event ausgelöst, indem die Methode OnPropertyChanged mit dem String Parameter, Name des Propertys, aufgerufen wird.

image

XAML View definieren

Die Datei MainWindow.xaml wird in Visual Studio geöffnet. In der Design Ansicht wird aus der Werkzeugleiste von Visual Studio je ein Button, TextBox und TextBlock Steuerelement auf das Formular gezogen.

image

Als nächstes wird in die XAML Code Ansicht gewechselt. Über das Attribut xmlns ist bereits von Visual Studio der Namensraum local vorbelegt der auf die Projektklassen verweist.

Tippen Sie <Windows.Resources> unterhalb des öffnenden Window Elements. Dann tippst du <l. Intellisense schlägt <local vor. Bestätigt wird per TAB. Als nächstes schlägt Intellisense die vorhandenen Klassen vor,  wähle das Viewmodel aus.

image

Dann wird der Name des so erzeugten Objektes vom Typ StarterViewModel mit dem Attribut x:Key als vm1 definiert. Das deklarativ erzeugte Objekt ist ident zu einem per new Operator im Code erzeugten.

image

Die Verbindung zwischen View und Viewmodel wird per Attribut DataContext eines XAML UI Elements hergestellt. Am einfachsten erfolgt dies auf oberster Ebene des XAML Trees und damit dem Grid Layout Element. Dem Attribut wird der Name des ViewModel Objektes VM1 zugewiesen. Dies erfolgt über {} und innerhalb einer Markupextension StaticResource.

datacontext

Der DataContext gilt für alle untergeordneten Elemente.

Die Eigenschaften Text (DependencyObject) der Kind Elemente Textblock und TextBox werden an das Property Zahl aus dem Viewmodel Objekt gebunden. Auch das geschieht mit einer Markup Extension, dieses Mal mit dem Binding Schlüsselwort.

   1:  Text="{Binding Zahl}"

Das Programm wird mit F5 gestartet. Wenn der Benutzer in das Textfeld die Zahl 1 eintippt und per TAB den Fokus verliert, wird die Bindung aktualisiert. Das Property Zahl enthält dann den neuen Wert, über den Setter der Klasse wird das Event ausgelöst. Der Textblock ist event Subscriber und aktualisiert adhoc die Anzeige.

image

Um nach jedem Tastendruck das Binding zu aktualisieren wird in XAML das Binding um zusätzliches Attribut ergänzt. Nur für die Textbox wird folgender Code ergänzt.

   1:  Text="{Binding Zahl,UpdateSourceTrigger=PropertyChanged}" 

Converter

Die Anzeige soll nun auf Wort statt Ziffer geändert werden, für 1 wird “Eins” angezeigt. Dazu wird eine neue Klasse dem Projekt hinzugefügt mit dem Namen zahlConverter.cs.

Die Klasse wird nach dem : um das Interface IValueConverter erweitert. Mit STR+ . wird der Namensraum per using System.Windows.Data eingebunden. Wieder per STR + . wird das Interface implementiert. Es sind dann die beiden Methoden Convert und ConvertBack in der Klasse vorhanden.

image

Für dieses Beispiel wird nur die Konvertierung von Zahl nach Wort benötigt. Ergänze die Methode Convert wie folgt.

   1:  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   2:          {
   3:              switch ((int) value)
   4:              {
   5:                  case 0:return "null";
   6:                  case 1: return "eins";
   7:                  case 2: return "zwei";
   8:                  case 3: return "drei";
   9:                  case 4: return "vier";
  10:                  case 5: return "fünf";
  11:                  case 6: return "sechs";
  12:                  case 7: return "sieben";
  13:                  case 8: return "acht";
  14:                  case 9: return "neun";
  15:              }
  16:              return "non";
  17:          }

 

Der ValueConverter wird ebenfalls deklarativ in XAML instanziiert und mit x:Key cv1 benannt.image.

Der Textblock erhält mit dem zusätzlichen Attribut Converter, innerhalb der Binding Deklaration das Converter Objekt zugewiesen. Da dieses statisch ist mit dem Keyword StaticResource.

   1:  Text="{Binding Zahl,Converter={StaticResource cv1}}"

 

image

Button Command

Um ohne Code Behind auszukommen und auf Daten des Viewmodels zugreifen zu können, muss das Button Click Event in der Viewmodel Klasse behandelt werden. Zuerst wird eine Klasse benötigt, die sich um die Delegation des Events kümmert. Diese muss das ICommand Interface implementieren.

Ausgehend vom einem Chef, der nichts selber macht, sondern auf Zuruf delegiert wird eine Klasse chefCommand.cs dem Projekt hinzugefügt.

image

Nach dem Klassennamen wird : und der Interfacename ICommand getippt. Per STR+ . wird per Using der Namensraum eingefügt. Per weiteren STR + .  Tastatur Kommando wird das Interface bzw die benötigten Methoden implementiert.

image

Entferne in der Methode CanExecute die Exception und schreibe return true;

Zusätzlich wird ein Readonly Field vom Typ Action definiert. Im Konstruktor der Klasse wird die Aufzurufende ViewModel Methode als Parameter vom Typ Action übergeben.

Im der Execute Methode wird dann die so übergebene ViewModel Methode aufgerufen.

   1:   private readonly Action _action;
   2:          public chefCommand(Action action)
   3:          {
   4:              _action = action;
   5:              
   6:          }
   7:          public void Execute(object parameter)
   8:          {
   9:             _action();

Nun wird wieder in der Datei StarterViewModel.cs eine Methode machsieben hinzugefügt. Diese setzt das private Feld auf zahl auf den Wert 7. Um das User Interface bzw. die Eigenschaften Text adhoc zu aktualisieren muss das Event PropertyChanged an alle Subscriber gesendet werden.

   1:   private void machsieben()
   2:          {
   3:              zahl = 7;
   4:              OnPropertyChanged("Zahl");
   5:              
   6:          }

Das XAML Button Command kann nur per Property vom Typ ICommand gebunden werden, das im letzten Schritt im ViewMode Code ergänzt wird. Der Getter des Propertys liefert eine Instanz der Chefklasse, mit den Namen der Viewmodel Methode.

   1:     public ICommand machsiebenCommand
   2:          {
   3:              get { return new chefCommand(machsieben); }
   4:          }

Im XAML WPF Code wird in Button das Attribut Command dem Binding zugewiesen.

image

Mehr Infos auf der Seiten von Microsoft.

Kommentare sind geschlossen