Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 6. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Das Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Strukturen und Enumerationen
7 Fehlerbehandlung und Debugging
8 Auflistungsklassen (Collections)
9 Generics – Generische Datentypen
10 Weitere C#-Sprachfeatures
11 LINQ
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 XML
15 Multithreading und die Task Parallel Library (TPL)
16 Einige wichtige .NET-Klassen
17 Projektmanagement und Visual Studio 2012
18 Einführung in die WPF und XAML
19 WPF-Layout-Container
20 Fenster in der WPF
21 WPF-Steuerelemente
22 Elementbindungen
23 Konzepte von WPF
24 Datenbindung
25 Weitere Möglichkeiten der Datenbindung
26 Dependency Properties
27 Ereignisse in der WPF
28 WPF-Commands
29 Benutzerdefinierte Controls
30 2D-Grafik
31 ADO.NET – Verbindungsorientierte Objekte
32 ADO.NET – Das Command-Objekt
33 ADO.NET – Der SqlDataAdapter
34 ADO.NET – Daten im lokalen Speicher
35 ADO.NET – Aktualisieren der Datenbank
36 Stark typisierte DataSets
37 Einführung in das ADO.NET Entity Framework
38 Datenabfragen des Entity Data Models (EDM)
39 Entitätsaktualisierung und Zustandsverwaltung
40 Konflikte behandeln
41 Plain Old CLR Objects (POCOs)
Stichwort

Download:
- Beispiele, ca. 62,4 MB

Buch bestellen
Ihre Meinung?

Spacer
Visual C# 2012 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2012

Visual C# 2012
Rheinwerk Computing
1402 S., 6., aktualisierte und erweiterte Auflage 2013, geb., mit DVD
49,90 Euro, ISBN 978-3-8362-1997-6
Pfeil 24 Datenbindung
Pfeil 24.1 Bindung benutzerdefinierter Objekte
Pfeil 24.1.1 Ein Objekt mit XAML-Code erzeugen und binden
Pfeil 24.1.2 Ein Objekt mit C#-Code erzeugen und binden
Pfeil 24.1.3 Aktualisieren benutzerdefinierter Objekte
Pfeil 24.2 Auflistungen binden
Pfeil 24.2.1 Allgemeine Gesichtspunkte
Pfeil 24.2.2 Anbindung an eine »ListBox«
Pfeil 24.2.3 Änderungen der Collection an die bindenden Elemente weiterleiten
Pfeil 24.3 Validieren von Bindungen
Pfeil 24.3.1 Die Validierung im Datenobjekt
Pfeil 24.3.2 Eine benutzerdefinierte »ValidationRule«
Pfeil 24.3.3 Validierung mit der Schnittstelle »IDataErrorInfo«
Pfeil 24.3.4 Fehlerhinweise individuell anzeigen
Pfeil 24.3.5 Ereignisauslösung bei einem Validierungsfehler
Pfeil 24.4 Daten konvertieren
Pfeil 24.4.1 Mehrfachbindungen und Konverterklassen
Pfeil 24.5 Datenbindung an ADO.NET- und LINQ-Datenquellen
Pfeil 24.5.1 Das Binden an ADO.NET-Objekte
Pfeil 24.5.2 Das Binden an LINQ-Ausdrücke

24 DatenbindungZur nächsten Überschrift

In Kapitel 22 haben wir uns mit den elementarsten Grundzügen der Datenbindung beschäftigt. Das Kapitel diente als Vorbereitung zu Kapitel 23, in dem wir uns mit Styles, Triggern und anderen WPF-Techniken beschäftigt haben, die zumindest auf Grundkenntnisse der WPF-Bindung aufsetzen.

In diesem Kapitel werden wir das Thema der Bindungen tiefer ausleuchten. Dabei werden wir uns mit der Bindung an Klassen und Listen und natürlich auch mit der Bindung an Datenbanken beschäftigen. Das Thema geht aber noch weiter, denn Bindungen verlangen durchaus auch die Validierung von Daten und manchmal auch eine Typkonvertierung. Das alles wird in diesem Kapitel behandelt.


Galileo Computing - Zum Seitenanfang

24.1 Bindung benutzerdefinierter ObjekteZur nächsten ÜberschriftZur vorigen Überschrift

Nehmen wir an, wir hätten in unserer Anwendung die Klasse Person wie folgt definiert:

public class Person {
private string _Name;
public string Name {
get { return _Name; }
set { _Name = value; }
}
private int? _Alter;
public int? Alter {
get { return _Alter; }
set { _Alter = value; }
}

private string _Adresse;
public string Adresse {
get { return _Adresse; }
set { _Adresse = value; }
}
}

Listing 24.1 Definition der Klasse »Person«

Ein Objekt dieser Klasse soll mit den Eigenschaften Name, Alter und Adresse an je eine TextBox gebunden werden. Um die Klasse noch ein wenig zu würzen, ist Alter ein null-fähiger Integer.

Sie haben zwei Möglichkeiten, ein Objekt vom Typ Person in einer WPF-Anwendung zu erzeugen:

  • im XAML-Code
  • mittels C#-Code

Beide Möglichkeiten wollen wir uns nun ansehen.


Galileo Computing - Zum Seitenanfang

24.1.1 Ein Objekt mit XAML-Code erzeugen und bindenZur nächsten ÜberschriftZur vorigen Überschrift

Im XAML-Code können innerhalb der Eigenschaft Objekte beliebiger Klassen erzeugt werden. Voraussetzung ist zunächst einmal, dass der Namespace, zu dem die Klasse gehört, bekannt gegeben wird. Sollte sich die Klasse zudem in einer externen Assembly befinden, ist auch diese zu nennen. Angenommen, die Klasse Person würde in der aktuellen Anwendung zum Namespace SimpleBinding gehören, könnte die Bekanntgabe wie folgt lauten:

<Window ... xmlns:local="clr-namespace:SimpleBinding">

Listing 24.2 Bekanntgabe des Namespaces

Das Namespace-Präfix ist frei wählbar, muss aber innerhalb des Window-Elements eindeutig sein. Hier lautet es local.

Im Resources-Abschnitt kann die Klasse Person nun instanziiert werden. Den Eigenschaften des Objekts kann auch sofort ein Anfangswert übergeben werden. Allerdings sind daran zwei Bedingungen geknüpft:

  • Damit die Klasse im XAML-Code instanziiert werden kann, muss sie einen parameterlosen Konstruktor haben.
  • Um den Eigenschaften Werte zuzuweisen, müssen diese als Property geprägt sein, d. h., sie müssen einen set- und get-Accessor haben.

Diese Bedingungen werden von der Klasse Person in Listing 24.1 erfüllt, so dass mit dem XAML-Code in Listing 24.3 ein Person-Objekt erzeugt werden kann.

<Window.Resources>
<local:Person x:Key="pers" Adresse="Köln" Name="Hans Glück" />
</Window.Resources>

Listing 24.3 Erzeugen eines Objekts vom Typ »Person« im XAML-Code

Den Eigenschaften Name und Adresse werden bereits zwei Eigenschaftswerte übergeben. Man darf natürlich nicht vergessen, der Ressource mit x:Key einen Identifier anzugeben.

Nun wollen wir die Eigenschaft Name des Objekts an die Eigenschaft Text einer TextBox binden. Zunächst einmal ist dazu ein Binding-Objekt notwendig, das innerhalb einer Markup-Extension erzeugt wird. Die Eigenschaft Source des Binding-Objekts beschreibt bekanntlich die Datenquelle. Hier müssen wir in einer weiteren, verschachtelten Markup-Erweiterung unter Angabe von StaticResource und dem Identifier die Ressource ansprechen und können mit Path an die gewünschte Eigenschaft des Person-Objekts binden.

<TextBox Text="{Binding Source={StaticResource pers}, Path=Name}" />

Listing 24.4 Bindung an die Eigenschaft »Name« des »Person«-Objekts


Galileo Computing - Zum Seitenanfang

24.1.2 Ein Objekt mit C#-Code erzeugen und bindenZur nächsten ÜberschriftZur vorigen Überschrift

Häufiger werden Sie auf die Fälle treffen, in denen ein Objekt im C#-Code erzeugt wird. Hier kommt die Eigenschaft DataContext ins Spiel, um das Objekt zu binden. In Abschnitt 22.3.3 wurde diese Eigenschaft bereits erwähnt. Noch einmal zur Erinnerung: Über eine Eigenschaft DataContext verfügen alle WPF-Elemente, die von FrameworkElement oder FrameworkContentElement abgeleitet sind. Folglich gehören zu diesen Elementen das Window, das Grid, das StackPanel, aber auch die TextBox.

Angenommen, wir würden mit C#-Programmcode ein Person-Objekt erzeugen und beabsichtigen, dieses mit dem Datenkontext des Window zu verbinden. Dann könnte die Bindung wie in Listing 24.5 gezeigt innerhalb des Konstruktors nach dem Aufruf der Methode InitializeComponent erfolgen.

// Beispiel: ..\Kapitel 24\SimpleBinding

public partial class MainWindow : Window {
Person pers = new Person { Name = "Manfred Fischer",
Alter = null,
Adresse="Köln, Bahnhofstraße" };

public MainWindow() {
InitializeComponent();
this.DataContext = pers;
}
}

Listing 24.5 Bindung an die Eigenschaft »DataContext«

Im XAML-Code erfolgt dann, wie in Listing 24.6 gezeigt, die Bindung an die Eigenschaften des Objekts.

<Window ...>
<Grid>
<Grid.RowDefinitions>
[...]
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
[...]
</Grid.ColumnDefinitions>
<StackPanel Background="Black" Grid.ColumnSpan="2">
<Label>Personendaten</Label>
</StackPanel>

<Label>Name:</Label>
< TextBox Text="{Binding Path=Name}"/>

<Label>Alter:</Label>
<TextBox Text="{Binding Path=Alter}"/>

<Label>Adresse:</Label>
<TextBox Text="{Binding Path=Adresse}"/>

</Grid>
</Window>

Listing 24.6 Bindung eines WPF-Elements an eine »DataContext«-Datenquelle

Abbildung

Abbildung 24.1 Ausgabe des Beispielprogramms »SimpleBinding«

Die Bindung erfolgt, ohne dass explizit die Datenquelle mit den Eigenschaften ElementName oder Source des Binding-Objekts angegeben wird. In diesen Fällen durchsucht WPF die DataContext-Eigenschaften des Elementbaums und fängt dabei beim aktuellen Element an. Wird hier keine Angabe gefunden, wird das in der Hierarchie weiter oben stehende Objekt abgefragt. In unserem Beispiel handelt es sich um das Grid. Hat auch die DataContext-Eigenschaft des Grid den Inhalt null, wird noch im Window gesucht. Hier wird die WPF fündig und bindet die unter Path angegebene Objekteigenschaft an das Steuerelement an.

Die Suche nach der ersten DataContext-Eigenschaft, die nicht null ist, kann man sich zunutze machen. Dieses Verhalten ermöglicht, durchaus auch mehrere Datenquellen an mehrere Elemente zu binden. Durch ein geschicktes Layout lassen sich auf diese Weise in einem Fenster mehrere Bereiche mit unterschiedlichen Datenquellen festlegen.

Binden von »null«-Werten

Das Alter eines Person-Objekts kann per Definition in der entsprechenden Klasse null sein. Damit ähnelt diese Eigenschaft vielen Feldern in Datenbanktabellen, die ebenfalls null zulassen. Die Konsequenz ist, dass in dem Element, das an ein solches Feld gebunden ist, nichts angezeigt wird (siehe Abbildung 24.1).

Die WPF bietet uns eine Möglichkeit einer vordefinierten Anzeige an, die immer dann erscheint, wenn der Feldwert null ist. Dazu gibt man der Eigenschaft TargetNullValue die Zeichenfolge an, die in diesem Fall angezeigt werden soll:

<TextBox Text="{Binding Path=Alter, TargetNullValue=[keine Angabe]}"/>

Listing 24.7 Binden von Feldern, deren Inhalt »null« ist

Natürlich sind die eckigen Klammern nicht unbedingt notwendig. Sie dienen vielmehr dazu, dem Anwender zu signalisieren, dass es sich hier um keinen gültigen Wert aus der Datenquelle handelt.


Galileo Computing - Zum Seitenanfang

24.1.3 Aktualisieren benutzerdefinierter ObjekteZur vorigen Überschrift

Wir wollen jetzt aber noch einen Schritt weiter gehen und die Daten des Objekts im Beispielprogramm SimpleBinding ändern. Die Änderung soll zur Laufzeit erfolgen, wenn der Anwender auf eine Schaltfläche klickt, die dem Fenster noch hinzugefügt werden muss.

<Button Name="button1" Click="button1_Click">
Objektdaten ändern
</Button>

Der Code des Ereignishandlers:

private void button1_Click(object sender, RoutedEventArgs e) {
pers.Name = "Hans Frisch";
pers.Alter = 35;
pers.Adresse = "Köln, Hauptstraße";
}

Listing 24.8 Codeergänzung des Beispielprogramms »SimpleBinding«

Mit dieser Ergänzung werden wir aber nicht, wie vielleicht erhofft, die geänderten Person-Daten in den Textboxen sehen. Diese zeigen immer noch die alten und nun auch nicht mehr aktuellen Daten an. Woher sollen die Textboxen auch die Informationen bekommen, dass sich das Objekt geändert hat?

Um dieses Problem zu lösen, bieten sich drei Alternativen an:

  • Sie können jede Eigenschaft als Abhängigkeitseigenschaft implementieren. Diese Variante ist mit verhältnismäßig viel Aufwand verbunden und wird bevorzugt bei Objekten benutzt, die eine grafische Präsentation haben. Zudem sollte man auch einen unter Umständen wesentlichen Nachteil der Dependency Properties nicht außer Acht lassen: Beim Multithreading kann es zu Problemen kommen.
  • Sie können in jeder Eigenschaft des Objekts ein separates Ereignis bereitstellen. Jedes Ereignis muss einen Bezeichner haben, bei dem zuerst der Eigenschaftsname angegeben ist, gefolgt vom Suffix Changed. In unserem Beispiel würden die drei erforderlichen Events NameChanged, AlterChanged und AdresseChanged lauten.
  • Die dritte Möglichkeit ist die Implementierung der Schnittstelle INotifyPropertyChanged. Dieses Interface gehört zum Namespace System.ComponentModel und schreibt das Ereignis PropertyChanged vor, das nach der Eigenschaftsänderung ausgelöst werden soll.

Die letztgenannte Lösung mit dem Interface drängt sich in unserem Beispiel geradezu auf. Daher implementieren wir dieses Interface und kapseln darüber hinaus das Ereignis in der geschützten Methode OnPropertyChanged:

public class Person : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
if (PropertyChanged != null)
PropertyChanged(this, e);
}
[...]
}

Listing 24.9 Implementieren des Interfaces »INotifyPropertyChanged«

Das Ereignis PropertyChanged muss ausgelöst werden, wenn sich eine Eigenschaft ändert, also innerhalb des set-Zweigs der Eigenschaftsmethoden. Dabei teilen Sie dem Konstruktor des PropertyChangedEventArgs-Objekts mit, wie der Name der geänderten Eigenschaft lautet.

public int? Alter {
get { return _Alter; }
set {
_Alter = value;
OnPropertyChanged(new PropertyChangedEventArgs("Alter"));
}
}

public string Name {
get { return _Name; }
set {
_Name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}

public string Adresse {
get { return _Adresse; }
set {
_Adresse = value;
OnPropertyChanged(new PropertyChangedEventArgs("Adresse"));
}
}

Listing 24.10 Ergänzung der Klasse »Person«

Jetzt ist die Klasse Person so weit vorbereitet, dass die an ein Objekt dieses Typs gebundenen Steuerelemente Notiz von einer Änderung an Adresse, Alter oder Name nehmen und den angezeigten Inhalt danach an die neuen Daten in der Quelle anpassen können.

Sie finden das komplette Beispielprogramm auf der Buch-DVD unter ...\Kapitel 24\ChangeNotificationSample.

Sie müssen noch nicht einmal in jedem set-Zweig das PropertyChanged-Ereignis auslösen. Es genügt, wenn Sie das Ereignis nur einmal auslösen und dem PropertyChangedEventArgs-Objekt einen Leerstring oder null übergeben. Der WPF wird damit signalisiert, dass sich alle Eigenschaften geändert haben; sie wird die Bindung der Elemente an das Objekt daraufhin neu aufbauen. Wählen Sie dann aber auch die Eigenschaft des Objekts, die als Letztes geändert wird, als diejenige aus, die den Event auslöst. Bezogen auf unseren Click-Ereignishandler in Listing 24.8 wäre das die Eigenschaft Adresse.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.

>> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2012

Visual C# 2012
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Rheinwerk Verlag GmbH 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de