Rheinwerk Computing < openbook > Rheinwerk 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

Jetzt 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

Rheinwerk Computing - Zum Seitenanfang

24.3 Validieren von BindungenZur nächsten Überschrift

Zu den wichtigen Charakteristiken einer Datenbindung gehört die Validierung. Unter der Validierung wird das Verhalten verstanden, falsche Eingaben oder nicht akzeptable Werte abzulehnen.

Die WPF bietet drei Wege an, um Daten zu validieren:

  • mit einem ExceptionValidationRule-Objekt
  • durch Ableiten der Klasse ValidationRule
  • durch Implementierung des Interfaces IDataErrorInfo

Eine Validierung wird nur stattfinden, wenn ein Wert aus dem Zielobjekt an die Datenquelle übergeben wird. Damit ist klar, dass eine Validierung nur im Zusammenhang mit den beiden Modi TwoWay und OneWayToSource durchgeführt werden kann.


Rheinwerk Computing - Zum Seitenanfang

24.3.1 Die Validierung im DatenobjektZur nächsten ÜberschriftZur vorigen Überschrift

Eine Datenvalidierung kann im set-Zweig einer Eigenschaft erfolgen. Betrachten wir exemplarisch die Klasse Person aus dem letzten Abschnitt und hier insbesondere deren Eigenschaft Alter. Das Alter darf zwar per Definition null sein, aber ein negatives Alter ergibt keinen Sinn. Also könnte man im set-Zweig eine Exception auslösen, wenn eine unzulässige negative Zuweisung erfolgt.

public class Person {
private int? _Alter;
public int? Alter
{
get { return _Alter; }
set {
if (value < 0)
throw new ArgumentException("Das Alter kann nicht negativ sein.");
else {
_Alter = value;
OnPropertyChanged(new PropertyChangedEventArgs("Alter"));
}
}
}
[...]
}

Listing 24.15 Die Eigenschaft »Alter« mit einer Exception im »set«-Zweig

Wir wollen uns nun das Verhalten einer WPF-Anwendung ansehen, falls ein Anwender zur Laufzeit einen ungültigen Wert an die Eigenschaft Alter eines Person-Objekts übergibt. Dazu soll das Window neben der Eingabemöglichkeit für Name und Alter auch in einer Spalte die in dem Moment aktuellen Objektdaten anzeigen.

Abbildung

Abbildung 24.4 Das Fensterlayout des Listings 24.16

Der Abbildung liegt der folgende XAML-Code zugrunde:

<Window >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label>Aktuelle Objektdaten:</Label>
<Label">Objektdaten ändern:</Label>
<Label Grid.Row="1" Content="{Binding Path=Name}"></Label>
<Label Grid.Row="2" Content="{Binding Path=Alter}"></Label>
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Path=Name}" />
<TextBox Grid.Column="1" Grid.Row="2"
Text="{Binding Path=Alter}" Margin="8" />
</Grid>
</Window>

Listing 24.16 XAML-Code des Dialogs aus Abbildung 24.4

Wenn Sie das Kompilat dieser Anwendung starten (also nicht aus Visual Studio heraus, sondern tatsächlich die exe-Datei), werden Sie feststellen, dass eine Änderung des Namens dazu führt, dass das Objekt den neuen Wert aus der entsprechenden TextBox übernimmt. Das gilt auch für das Alter – zumindest solange Sie einen gültigen Wert übergeben. Tragen Sie jedoch einen negativen Wert ein, wird dieser nicht an das Objekt übergeben. So soll es auch sein. Aber andererseits wird der Anwender überhaupt nicht davon in Kenntnis gesetzt, dass der negative Wert nicht übernommen worden ist. Es wird auch keine Ausnahme ausgelöst, wie man vielleicht vermuten könnte.

Damit die Ausnahme zumindest eine Warnung beim Benutzer hervorruft, muss der Fehler der Bindung mitgeteilt werden. Das geschieht über die Eigenschaft ValidationRules des Binding-Objekts, der ein Objekt vom Typ ExceptionValidationRule übergeben wird:

[...]
<TextBox UpdateSourceTrigger="PropertyChanged">
<Binding Path="Alter">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>

</Binding>
</TextBox>
[...]

Listing 24.17 Änderung der Bindung der TextBox

Mit dieser Änderung im Vergleich zu Listing 24.16 erreichen wir, dass die TextBox bei einer Fehleingabe innerhalb eines roten Rahmens dargestellt wird und somit dem Anwender zumindest einen optischen Hinweis liefert. Natürlich wird auch weiterhin der ungültige Wert nicht dem Person-Objekt übergeben. Beachten Sie, dass auch die Eigenschaft UpdateSourceTrigger auf PropertyChanged der TextBox eingestellt worden ist. Damit wird dem Anwender der Fehler bereits signalisiert, wenn er ein Minuszeichen einträgt.

Anstatt des doch ziemlich aufwendigen XAML-Codes des Listings 24.17 können Sie auch eine kürzere Variante benutzen. Dazu legen Sie die Eigenschaft ValidatesOnExceptions auf True fest, wie in Listing 24.18 gezeigt wird:

<TextBox Text="{Binding Path=Alter, UpdateSourceTrigger=PropertyChanged, 
ValidatesOnExceptions=True}" />

Listing 24.18 Die Eigenschaft »ValidatesOnExceptions«

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


Rheinwerk Computing - Zum Seitenanfang

24.3.2 Eine benutzerdefinierte »ValidationRule«Zur nächsten ÜberschriftZur vorigen Überschrift

Die nächste Variante eignet sich besonders dann,wenn Sie keine Möglichkeit haben, die Datenklasse (in unserem Beispiel also die Klasse Person) zu verändern. Die Vorgehensweise ist sehr einfach: Sie stellen eine Klasse bereit, die von ValidationRule abgeleitet ist, und überschreiben die geerbte Methode Validate.

Bezugnehmend auf die Eigenschaft Alter einer Person könnte die Validierung wie im folgenden Listing gezeigt aussehen:

public class AgeValidationRule : ValidationRule {
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
int wert = Convert.ToInt32(value);
if (wert < 0)
return new ValidationResult(false, "Das Alter darf nicht negativ sein.");
return new ValidationResult(true, null);
}
}

Listing 24.19 Bereitstellen einer Klasse vom Typ »ValidationRule«

Im ersten Parameter der Methode Validate wird der Wert übergeben, der validiert werden soll. Unabhängig davon, ob die Validierung zu einem positiven oder negativen Ergebnis führt, wird ein ValidationResult-Objekt erzeugt. Der Konstruktor von ValidationResult beschreibt zwei Parameter. Der erste ist der entscheidende, denn er gibt über einen Boolean bekannt, ob erfolgreich validiert worden ist (true) oder die Validierung gescheitert ist (false). Der zweite Parameter des Konstruktors dient dazu, Informationen zur fehlgeschlagenen Validierung zu liefern.

Im XAML-Code ändert sich im Vergleich zu dem aus Listing 24.17 nicht viel. Zunächst müssen Sie den Namespace bekannt geben, in dem die Klasse AgeValidationRule definiert ist. Der Eigenschaft ValidationRules des Binding-Objekts geben Sie anschließend noch ein Objekt der Klasse an.

<Window  
xmlns:local="clr-namespace:ValidationRuleSample"
...>
[...]
<TextBox Grid.Column="1" Grid.Row="2">
<Binding Path="Alter" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:AgeValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
[...]
</Window>

Listing 24.20 Bekanntgabe des »ValidationRule«-Objekts im XAML-Code

Das Verhalten zur Laufzeit unterscheidet sich nicht von dem Verhalten, wenn Sie den Typ ExceptionValidationRule benutzen.

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


Rheinwerk Computing - Zum Seitenanfang

24.3.3 Validierung mit der Schnittstelle »IDataErrorInfo«Zur nächsten ÜberschriftZur vorigen Überschrift

Kommen wir nun zur dritten Validierungsvariante, bei der das Interface IDataErrorInfo eine Rolle spielt. Die Schnittstelle IDataErrorInfo wird von der Datenklasse implementiert – in unserem Beispiel somit von der Klasse Person. Hier stellt sich zunächst einmal die Frage, warum den Datenklassen hiermit noch eine weitere Validierungsmöglichkeit geboten wird? Im Grunde genommen hängt es damit zusammen, dass eine Ausnahme nur dann ausgelöst werden sollte, wenn schwerwiegende Fehler aufgetreten sind. Das lässt sich aber im Zusammenhang mit einer falschen Benutzereingabe kaum behaupten. Gewissermaßen wird dann mit Kanonen auf Spatzen geschossen.

IDataErrorInfo verpflichtet zur Implementierung von zwei Eigenschaften: Error und this, also einem Indexer. Im Gegensatz zu anderen Technologien, denen auch die Schnittstelle zur Verfügung steht, nutzt die WPF aber nur den Indexer. Sehen wir uns jetzt die Überarbeitung der Klasse Person an.

public class Person : INotifyPropertyChanged, IDataErrorInfo {
public string Error {
get { return null; }
}
public string this[string propertyName] {
get
{
if (propertyName == "Alter")
{
if(_Alter < 0)
return "Das Alter darf nicht negativ sein.";
}
return null;
}
}
private int? _Alter;
public int? Alter {
get { return _Alter; }
set {
_Alter = value;
OnPropertyChanged(new PropertyChangedEventArgs("Alter"));
}
}
}

Listing 24.21 Das Interface »IDataErrorInfo« zur Validierung verwenden

Dem Indexer wird die zu prüfende Eigenschaft als Zeichenfolge übergeben. Die Validierung erfolgt nach Feststellung der Eigenschaft, die für den Aufruf des Indexers sorgt. Anschließend prüft der übliche Code, ob die Eigenschaft einen gültigen Wert hat. Beachten Sie, dass der neue Wert bereits in das private Feld geschrieben worden ist, unabhängig von der Akzeptanz. Wird der Inhalt der Eigenschaft als Fehler erkannt, wird eine einfache Zeichenfolge zurückgegeben, die damit den Fehler signalisiert. Ansonsten ist der Rückgabewert null.

Im XAML-Code muss der Eigenschaft ValidationRules nur ein DataErrorValidationRule-Objekt übergeben werden:

[...]
<TextBox>
<Binding Path="Alter" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<DataErrorValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox>
[...]

Listing 24.22 Übergabe eines »DataErrorValidationRule«-Objekts

Auch in diesem Fall können Sie im XAML-Code alternativ eine kürzere Schreibweise verwenden:

<TextBox Text="{Binding Path=Alter, ValidatesOnDataErrors=True}" />

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


Rheinwerk Computing - Zum Seitenanfang

24.3.4 Fehlerhinweise individuell anzeigenZur nächsten ÜberschriftZur vorigen Überschrift

Die Anzeige des Fehlers durch einen roten Rahmen ist recht unscheinbar. Zudem werden die Fehlermeldungen, die von der Validierung bereitgestellt werden, nicht angezeigt. Um eine aussagekräftigere Fehlermeldung anzuzeigen, können Sie für die Fehlermeldungen ein eigenes Template schreiben. Dabei betritt die Klasse ControlTemplate, die wir bereits in Kapitel 23 kennengelernt haben, erneut die Bühne.

Aber zuvor wenden wir uns kurz der Klasse Validation zu, die dem Datenziel einer Bindung drei Eigenschaften anhängt, die wir im folgenden XAML-Code auch verwenden werden: Es sind Errors, HasError und ErrorTemplate. Die Beschreibung der genannten Eigenschaften können Sie der folgenden Tabelle entnehmen.

Tabelle 24.2 Die Eigenschaften der Klasse »Validation«

Eigenschaft Beschreibung

Errors

Ruft die Liste aller ValidationError-Objekte des gebundenen Elements ab.

ErrorsTemplate

Diese Eigenschaft legt das ControlTemplate fest, das bei Validierungsfehlern angezeigt wird. Die Vorgabe ist ein roter Rahmen.

HasError

Diese Eigenschaft liefert true, wenn ein Binding-Objekt einen Fehler zurückliefert.

Ausgehend von unserem letzten Beispielprogramm (IDataErrorInfoSample) wollen wir nun die Fehlermeldungen in einem ToolTip zur Anzeige bringen. Zur optischen Ergänzung wird der Rahmen um die fehlerauslösende TextBox in der Farbe Gelb gezeichnet, und vor der TextBox werden drei Sternchensymbole angezeigt. In Abbildung 24.5 können Sie das Resultat unserer Bestrebungen bereits bewundern.

Abbildung

Abbildung 24.5 Ein Template für eine Fehlermeldung

Insgesamt ist der dafür notwendige XAML-Code schon relativ komplex.

<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Left" Foreground="Red"
FontSize="14" FontWeight="Bold"
ToolTip="{Binding ElementName=adorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
***
</TextBlock>
<Border BorderBrush="Yellow" BorderThickness="2">
<AdornedElementPlaceholder Name="adorner" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Listing 24.23 Grundstruktur der benutzerdefinierten Fehlermeldung

Es wird zuerst ein Style definiert. Dieser beschreibt die Eigenschaft Validation.ErrorTemplate eines TextBox-Elements. Tritt ein Validierungsfehler auf, wird dieser Style aktiv. Das Layout der Fehleranzeige wird innerhalb eines ControlTemplate-Elements beschrieben.

Mit Border wird ein Rahmen beschrieben, der um ein anderes Element gezeichnet wird. Hier ist dieses Element vom Typ AdornedElementPlaceholder. Ein AdornedElementPlaceholder wird in einem ControlTemplate verwendet und stellt einen Platzhalter für das Element dar, das mit der Fehlermeldung markiert sein soll. Adorner werden meist relativ zu dem Element positioniert, an das der Adorner gebunden ist, und stehen stets visuell im Vordergrund.

Mit dem Ausdruck

ToolTip="{Binding ElementName=adorner, Path=AdornedElement ...

wird das unter dem AdornedElementPlaceholder gelegene Element abgerufen, was in unserem Beispiel die TextBox ist. Um auf den aktuellen Fehler zugreifen zu können, muss die Eigenschaft Validation.Errors der TextBox abgerufen werden. Hierbei handelt es sich um eine angefügte Eigenschaft, daher sind die runden Klammern anzugeben. Danach wird mit

Path=AdornedElement.(Validation.Errors)[0].ErrorContent}

auf den ersten Fehler aus der Collection zugegriffen und dessen Fehlerbeschreibung abgerufen.

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


Rheinwerk Computing - Zum Seitenanfang

24.3.5 Ereignisauslösung bei einem ValidierungsfehlerZur vorigen Überschrift

Natürlich können Sie bei einem Validierungsfehler auch ein Ereignis auslösen – anstatt oder zusätzlich zu einer optischen Anzeige, wie im letzten Abschnitt erläutert. Dazu muss die Eigenschaft NotifyOnValidationError der Bindung auf true gesetzt werden, z. B.:

<Binding Path="Alter" UpdateSourceTrigger="PropertyChanged" 
NotifyOnValidationError="True">

Listing 24.24 Zulassen der Ereignisauslösung

Der ausgelöste Validation.Error-Event wird im Elementbaum noch oben gebubbelt. Daher bietet es sich an, die Registrierung des Ereignishandlers im Container-Element vorzunehmen. Somit kann der Ereignishandler auch von mehreren Steuerelementen genutzt werden.

<Grid Validation.Error="Grid_Error">
[...]
</Grid>

Listing 24.25 Registrierung des Ereignishandlers

Der zweite Parameter des Ereignishandlers ist vom Typ ValidationErrorEventArgs. Dieser Typ beinhaltet in seiner Eigenschaft Error zahlreiche Informationen, die den Validierungsfehler detailliert beschreiben. So können Sie selbstverständlich auch die Fehlerbeschreibung aus der Eigenschaft ErrorContent abrufen, wie im folgenden Listing gezeigt wird.

private void Grid_Error(object sender, ValidationErrorEventArgs e)
{
MessageBox.Show(e.Error.ErrorContent.ToString());
}

Listing 24.26 Der Ereignishandler des Events »Validation.Error«



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual C# 2012

Visual C# 2012
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: C/C++






 C/C++


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
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.


Nutzungsbestimmungen | Datenschutz | Impressum

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

Cookie-Einstellungen ändern