Saturday, February 1, 2014

DataBinding “ohne” INotifyPropertyChanged, aber mit Fody

Einleitung

Datenbindung in WPF ohne INotifyPropertyChanged, ja geht denn das? Jein, natürlich nicht. Aber ich möchte euch ein NuGet Package vorstellen, welches euch die Arbeit erheblich erleichtern kann, wenn ihr gerade eine WPF Applikation mit Datenanbindung an die GUI, vermutlich mittels MVVM, beginnen wollt. Legen wir also gleich einmal los.

Den kompletten Beispiel-Code findet ihr hier

DataBinding ohne INotifyPropertyChanged

Zuerst fügen wir eine neue Klasse Employee zu unserem Projekt hinzu, dieser geben wir 2 Properties – FirstName und LastName.

Code:
    class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Kümmern wir uns um die GUI, diese sollte so aussehen:
image

An die beiden TextBoxen wollen wir unsere Klasse Employee mittels DataBinding anbinden.
Der XAML Code sieht so aus:
  <Grid>
        <TextBox Text="{Binding FirstName}" 
            HorizontalAlignment="Left" Height="23" Margin="62,43,0,0"  
VerticalAlignment
="Top" Width="120"/>
        <TextBox Text="{Binding LastName}" 
            HorizontalAlignment="Left" Height="23" Margin="62,104,0,0" 
VerticalAlignment
="Top" Width="120"/>
        <Label Content="FirstName" HorizontalAlignment="Left" Margin="62,10,0,0" 
VerticalAlignment
="Top"/>
        <Label Content="LastName" HorizontalAlignment="Left" Margin="62,73,0,0" 
VerticalAlignment
="Top"/>
        <Button Content="OK" HorizontalAlignment="Left" Margin="62,156,0,0" 
           VerticalAlignment="Top" Width="120" Click="Button_Click"/>
    </Grid>

Nun wollen wir noch eine neue (leere) Instanz der Klasse Employee an unser Fenster binden und im Click Event wollen wir die Werte anpassen und in einer MessageBox ausgeben. Im Idealfall sehen wir den neuen Vornamen und den neuen Nachnamen in der MessageBox UND in den TextBoxen (das wäre ja der Sinn der Datenbindung).


Code:
    public partial class MainWindow : Window
{
Employee employee;

public MainWindow()
{
InitializeComponent();

employee = new Employee();
this.DataContext = employee;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
employee.FirstName = "Berndt";
employee.LastName = "Hamboeck";

MessageBox.Show(string.Format("{0} {1}",
                employee.FirstName, employee.LastName), "Employee Info",
MessageBoxButton.OK, MessageBoxImage.Information);
}
}

Wenn wir unser Projekt laufen lassen, so können wir sehr schön erkennen, dass die Werte zwar in der Meldung ausgegeben werden, den Weg aber nicht zu den TextBoxen finden.
image
Ganz klar, werden einige von euch nun denken, kann ja nicht funktionieren, da wir ja noch INotifyPropertyChanged implementieren müssen.
Stimmt, aber genau das wollen wir uns ersparen und werden ein NuGet Package, mit dem Namen PropertyChanged.Fody zu unserem Projekt hinzufügen.

DataBinding mit PropertyChanged.Fody

Öffnen wir also das NuGet Fenster in Visual Studio 2013 und fügen dieses Package hinzu.
image
In dem neuen Fenster sucht Ihr am Besten nach Fody und wählt dann das PropertyChanged.Fody Paket zur Installation aus:
image
Alternativ könnt Ihr das Package auch über die Nuget Packet Manager Console installieren, diese findet Ihr im Menüpunkt Tools.
image
Dort gebt Ihr folgenden Befehl in der Konsole ein:
Install-Package PropertyChanged.Fody

Wie immer Ihr euch entscheidet, das Resultat sollte sein, dass Ihr die Referenz in eurem Projekt wieder findet:
image
Nun müssen wir noch die Annotation [ImplementPropertyChanged] zu unserer Klasse hinzufügen und uns den NameSpace holen.
image

Das Endresultat sieht in der Employee-Klasse dann so aus:



Code:
using PropertyChanged;

namespace FodySample
{
[ImplementPropertyChanged]
class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
Jetzt lassen wir die Applikation noch einmal laufen, und wir sehen, dass die veränderten Werte nun auch in den TextBoxen zu sehen sind.
image
Wenn wir uns den kompilierten Code ansehen, dann können wir erkennen, dass Fody uns einfach nur die Arbeit abnimmt und zwar während der Kompilierung unseres Projektes. Der generierte Code sieht so aus:
Code:
namespace FodySample
{
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;

internal class Employee : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

public virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public string FirstName
{
[CompilerGenerated]
get
{
return this.<FirstName>k__BackingField;
}
[CompilerGenerated]
set
{
if (!string.Equals(this.<FirstName>k__BackingField, value, StringComparison.Ordinal))
{
this.<FirstName>k__BackingField = value;
this.OnPropertyChanged("FirstName");
}
}
}

public string LastName
{
[CompilerGenerated]
get
{
return this.<LastName>k__BackingField;
}
[CompilerGenerated]
set
{
if (!string.Equals(this.<LastName>k__BackingField, value, StringComparison.Ordinal))
{
this.<LastName>k__BackingField = value;
this.OnPropertyChanged("LastName");
}
}
}
}
}


Zusammenfassung

WPF und Datenanbindung und MVVM ist eine tolle Art Applikationen zu entwickeln. Das funktioniert out-of-the-box schon sehr gut, aber das Fody Package kann uns doch einiges an Arbeit abnehmen. Somit bleibt mehr Zeit für die eigentlich wichtigen Dinge in einem Software-Projekt: Das Projekt muss fertig werden und die Wünsche der Anwender möglichst gut abbilden, ohne dass wir Entwickler mit der Technologie zu kämpfen haben.

No comments:

CSharpCodeFormatter