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

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 22 Konzepte von WPF
Pfeil 22.1 Abhängige und angehängte Eigenschaften
Pfeil 22.1.1 Abhängige Eigenschaften
Pfeil 22.1.2 Angehängte Eigenschaften
Pfeil 22.2 Ressourcen
Pfeil 22.2.1 Definition
Pfeil 22.2.2 Zeitpunkt der Wertbestimmung
Pfeil 22.2.3 Abrufen von Systemressourcen
Pfeil 22.3 Stile
Pfeil 22.3.1 Einfache Stile
Pfeil 22.3.2 Typisierte Stile
Pfeil 22.4 Trigger
Pfeil 22.4.1 Eigenschaftstrigger
Pfeil 22.4.2 Ereignistrigger
Pfeil 22.4.3 Datentrigger
Pfeil 22.5 Kommandos
Pfeil 22.5.1 Vordefiniert
Pfeil 22.5.2 Beispielanwendung
Pfeil 22.5.3 Kommando-Ziel
Pfeil 22.5.4 Kommandos an Ereignisse binden
Pfeil 22.5.5 Kommandos programmieren
Pfeil 22.6 Datenbindung
Pfeil 22.6.1 Einfache Datenbindung
Pfeil 22.7 Bindungsarten
Pfeil 22.7.1 Aktualisierung der Quelle
Pfeil 22.7.2 Datenbindungsquellen
Pfeil 22.7.3 Auflistungen anbinden


Rheinwerk Computing - Zum Seitenanfang

22.7 Bindungsarten Zur nächsten ÜberschriftZur vorigen Überschrift

Bisher haben wir uns nicht darum gekümmert, nach welchen Regeln die Synchronisation der verbundenen Eigenschaften funktioniert. Mit dem Attribut Mode legen Sie fest, in welchen Richtungen die Bindung aktiv ist. Beispielsweise können Sie die Standardvorgaberichtung von der Quelle zum Ziel auch umkehren. Dann aktualisiert das Ziel die Quelle.

Tabelle 22.2 listet die möglichen Modi vom Typ der Enumeration BindingMode auf.


Tabelle 22.2 Bindungsarten

Bindungstyp Übertragung des Wertes

Default

Der für die Eigenschaft definierte Standard

OneTime

Einmalig von der Quelle zum Ziel, danach Kappen der Verbindung

OneWay

Von der Quelle zum Ziel. Nach Änderung der Daten im Zielobjekt wird die Verbindung gekappt.

OneWayToSource

Von der Quelle zum Ziel. Ändert sich der Wert in der Quelle, bleibt zwar die Bindung bestehen, aber die Daten werden nicht übertragen.

TwoWay

Von der Quelle zum Ziel und umgekehrt


Das folgende Beispielprogramm demonstriert anschaulich die Auswirkung der verschiedenen Modi. Dazu hat das Formular in Abbildung 22.6 für jeden Modus je zwei Textboxen.

Abbildung 22.6 Demonstration der Bindungsarten


'...\WPFKonzepte\Datenbindung\Modus.xaml

<Window ...>
  <Window.Resources>
    <Style TargetType="{x:Type Control}">
      <Setter Property="Margin" Value="2" />
    </Style>
    <Style TargetType="{x:Type TextBox}">
      <Setter Property="Margin" Value="2" />
    </Style>
  </Window.Resources>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="100" />
      <ColumnDefinition Width="*" /><ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition /> <RowDefinition /> <RowDefinition />
      <RowDefinition /> <RowDefinition /> <RowDefinition />
    </Grid.RowDefinitions>

    <Label Grid.Column="0" Grid.Row="0" Content="Bindungsart" />
    <Label Grid.Column="1" Grid.Row="0" Content="Quelle" />
    <Label Grid.Column="2" Grid.Row="0" Content="Ziel" />
    <Label Grid.Column="0" Grid.Row="1" Content="Default" />
    <TextBox Name="DefaultQuelle" Text="Test" Grid.Column="1" Grid.Row="1"/>
    <TextBox Name="DefaultZiel" Grid.Column="2" Grid.Row="1"
      Text="{Binding ElementName=DefaultQuelle, Path=Text}"/>
    <Label Grid.Column="0" Grid.Row="2" Content="OneWay" />
    <TextBox Name="OneWayQuelle" Text="Test" Grid.Column="1" Grid.Row="2" />
    <TextBox Name="OneWayZiel" Grid.Column="2" Grid.Row="2"
      Text="{Binding ElementName=OneWayQuelle, Path=Text, Mode=OneWay}" />
    <Label Grid.Column="0" Grid.Row="3" Content="TwoWay" />
    <TextBox Name="TwoWayQuelle" Text="Test" Grid.Column="1" Grid.Row="3" />
    <TextBox Name="TwoWayZiel" Grid.Column="2" Grid.Row="3"
      Text="{Binding ElementName=TwoWayQuelle, Path=Text, Mode=TwoWay}" />
    <Label Grid.Column="0" Grid.Row="4" Content="OneTime" />
    <TextBox Name="OneTimeQuelle" Text="Test" Grid.Column="1" Grid.Row="4" />
    <TextBox Name="OneTimeZiel" Grid.Column="2" Grid.Row="4"
             Text="Test" Focusable="False" />
    <Label Grid.Column="0" Grid.Row="5" Content="OneWayToSource" />
    <TextBox Name="OneWayToSourceQuelle" Text="Test"
             Grid.Column="1" Grid.Row="5"/>
    <TextBox Name="OneWayToSourceZiel" Grid.Column="2" Grid.Row="5"
             Text="{Binding ElementName=OneWayToSourceQuelle,
             Path=Text, Mode=OneWayToSource, FallbackValue=Test}" />
  </Grid>
</Window>

Die Eigenschaft Text einer TextBox ist standardmäßig auf TwoWay eingestellt. Änderungen in der Quelle werden sofort vom Ziel angezeigt. Ändern Sie aber den Inhalt im Ziel, müssen Sie erst die TextBox verlassen, ehe die Änderung in der Quelle wirksam wird.


Rheinwerk Computing - Zum Seitenanfang

22.7.1 Aktualisierung der Quelle Zur nächsten ÜberschriftZur vorigen Überschrift

Die eben beschriebene Verhaltensweise ist nicht immer wünschenswert. Sie lässt sich mit dem Attribut UpdateSourceTrigger vom Typ der gleichnamigen Enumeration steuern (siehe Tabelle 22.3).


Tabelle 22.3 Die Enumeration »UpdateSourceTrigger«

Konstante Beschreibung

Default

Komponentenabhängige Standardeinstellung. Oft ist dies PropertyChanged, seltener LostFocus (wie bei einer TextBox).

Explicit

Änderung erfolgt nur durch expliziten Aufruf der UpdateSource-Methode des Zielobjekts.

LostFocus

Die Quelle wird aktualisiert, wenn das Ziel den Fokus verliert.

PropertyChanged

Die Aktualisierung erfolgt bei jeder Änderung (ressourcenintensiv!).


Um eine Zweiwegeaktualisierung in Echtzeit zu erreichen, geben Sie im Binding-Abschnitt statt Mode das Attribut UpdateSourceTrigger an:

<TextBox Name="TwoWayZiel" Grid.Column="2" Grid.Row="3"
  Text="{Binding ElementName=TwoWayQuelle, Path=Text,
         UpdateSourceTrigger=PropertyChanged }" />

Sehen wir uns abschließend noch die Einstellung Explicit an. Hierbei wird der Anstoß zur Aktualisierung der Werte von außen gegeben. Das kann beispielsweise das Drücken der Taste Enter -Taste sein oder auch das Click-Ereignis einer Schaltfläche.

Die beiden folgenden Codefragmente zeigen, wie das Drücken der Taste Enter -Taste in der TextBox namens unten (dem »Ziel«) zum Aktualisieren einer anderen TextBox namens oben (der »Quelle«) führt.

<StackPanel>
  <TextBox Name="oben" Height="100"></TextBox>
  <TextBox Name="unten" Height="100" KeyDown="Gedrückt"
    Text="{Binding ElementName=oben, Path=Text,
           UpdateSourceTrigger=Explicit}" />
</StackPanel>

Die Bindung erfolgt im XAML-Code. Daher muss im Visual Basic-Code zuerst mit der Methode GetBindingExpression ein BindingExpression-Objekt abgerufen werden, um darauf die Methode UpdateSource aufzurufen.

Private Sub Gedrückt(sender As Object, e As KeyEventArgs)
  If e.Key = Key.Enter Then _
    unten.GetBindingExpression(TextBox.TextProperty).UpdateSource()
End Sub

Rheinwerk Computing - Zum Seitenanfang

22.7.2 Datenbindungsquellen Zur nächsten ÜberschriftZur vorigen Überschrift

Bindung an beliebige Objekte

Angenommen, Sie haben eine Klasse Person implementiert. Objekte dieses Typs sollen als Datenquelle dienen und in einem Window-Objekt eingebunden werden. Damit werden auch Forderungen an die Implementierung der Klasse gestellt:

  • Implementierung der Schnittstelle System.ComponentModel.INotifyPropertyChanged
  • Definition eines parameterlosen Konstruktors
  • Datenquellen sind nur Eigenschaften mit öffentlicher Eigenschaftsmethode, dagegen können öffentliche Felder (Variablen auf Klassenebene) nicht gebunden werden.

Über die Schnittstelle INotifyPropertyChanged wird das Ereignis PropertyChanged eingeführt, das immer dann ausgelöst wird, wenn sich eine bindungsfähige Eigenschaft ändert.

Es folgt nun die Definition der Klasse Person. Bei Änderung der Eigenschaften Zuname oder Alter wird die Methode OnPropertyChanged aufgerufen, die ihrerseits das Ereignis PropertyChanged auslöst.


'...\WPFKonzepte\Datenbindung\Person.xaml

Imports System.ComponentModel
Public Class Person : Implements INotifyPropertyChanged
  ' Ereignis aus der Schnittstelle INotifiyPropertyChanged

  Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
    Implements INotifyPropertyChanged.PropertyChanged

  Private zu As String
  Public Property Zuname() As String
    Get
      Return zu
    End Get
    Set(ByVal value As String)
      zu = value
      OnPropertyChanged("Zuname")
    End Set
  End Property

  Private alt As Integer
  Public Property Alter() As Integer
    Get
      Return alt
    End Get
    Set(ByVal value As Integer)
      alt = value
      OnPropertyChanged("Alter")
    End Set
  End Property

  Protected Sub OnPropertyChanged(ByVal prop As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
  End Sub

End Class

Im XAML-Code wird Person aus der aktuellen Anwendung benötigt sowie Typen aus dem Namensraum System. Beide Namensräume werden in der XAML-Datei angegeben.

xmlns:clr="clr-namespace:System;assembly=mscorlib"
xmlns:src="clr-namespace:Datenbindung"

Nun kann die Klasse Person auch in der XAML-Datei verwendet werden. Um Person in der XAML-Datei zu instanziieren, verwendet man den Ressourcenabschnitt. Optional können den Eigenschaften sofort Werte zugewiesen werden.

<Window.Resources>
  <src:Person x:Key="pers1" Zuname="Schmidt" Alter="43" />
</Window.Resources>

Danach können Sie die Möglichkeiten der Datenbindung benutzen. In unserem Beispiel werden Zuname und Alter der Person in zwei Textboxen angezeigt.

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="50" /><ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="25" /><RowDefinition Height="25" />
  </Grid.RowDefinitions>
  <Label Grid.Column="0" Grid.Row="0">Zuname:</Label>
  <TextBox Grid.Column="1" Grid.Row="0" Name="txtZuname"
           Text="{Binding Source={StaticResource pers1}, Path=Zuname}" />
  <Label Grid.Column="0" Grid.Row="1">Alter:</Label>
  <TextBox Grid.Column="1" Grid.Row="1" Name="txtAlter"
           Text="{Binding Source={StaticResource pers1}, Path=Alter}" />
</Grid>

Eine alternative Variante der Datenbindung bietet sich an, wenn das Objekt zahlreiche Eigenschaften hat und mehrere Komponenten an diese Eigenschaften gebunden werden. Weisen Sie dazu der Eigenschaft DataContext des Containers die Ressource zu. Wird in einem untergeordneten Element keine Datenquelle angegeben, sucht das Element in der Hierarchie aufwärts nach einer DataContext-Spezifikation.

<Grid DataContext="{StaticResource pers1}">
  ...
  <Label Grid.Column="0" Grid.Row="0">Zuname:</Label>
  <TextBox Grid.Column="1" Grid.Row="0" Name="txtZuname"
           Text="{Binding Path=Zuname}" />
  <Label Grid.Column="0" Grid.Row="1">Alter:</Label>
  <TextBox Grid.Column="1" Grid.Row="1" Name="txtAlter"
           Text="{Binding  Path=Alter}" />
</Grid>

Zugriff auf eine Instanz im XAML-Code

Wollen Sie im Visual Basic-Code auf ein im XAML-Code erzeugtes Objekt zugreifen, zum Beispiel um den Wert einer Eigenschaft zu ändern, dann müssen Sie sich zuerst die Referenz auf das im XAML-Code erzeugte Objekt besorgen. Hier hilft die Methode FindResource der Klasse FrameworkElement weiter, einer Basisklasse von Window. Der Methode wird als Argument das im XAML-Code erzeugte Objekt übergeben. Der Rückgabewert muss noch in den richtigen Typ konvertiert werden.

Private Sub Ändern(sender As Object, e As RoutedEventArgs)
  Dim pers As Person = CType(FindResource("pers"), Person)
  MessageBox.Show("Name und Alter: " & pers.Zuname & ", " & pers.Alter)
  pers.Zuname = "Schmidt-Gerhards"
End Sub

Umgekehrt können Sie im Code ein Objekt erzeugen und an DataContext übergeben.

Private Sub Erzeugen(sender As Object, e As RoutedEventArgs)
  Dim pers As New Person()
  pers.Zuname = "Fischer"
  pers.Alter = 55
  grid1.DataContext = pers
End Sub

Der passende XAML-Code dazu sieht so aus:


'...\WPFKonzepte\Datenbindung\Instanz.xaml

<Window xmlns:src="clr-namespace:Datenbindung" ...>
...
<Window.Resources>
  <src:Person x:Key="pers1" Zuname="Schmidt" Alter="43" />
</Window.Resources>

<Grid Name="grid1">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="50" /><ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition/><RowDefinition/><RowDefinition/><RowDefinition/>
  </Grid.RowDefinitions>
  <Label Grid.Column="0" Grid.Row="0">Zuname:</Label>
  <TextBox Grid.Column="1" Grid.Row="0" Name="txtZuname"
           Text="{Binding  Path=Zuname}" />
  <Label Grid.Column="0" Grid.Row="1">Alter:</Label>
  <TextBox Grid.Column="1" Grid.Row="1" Name="txtAlter"
           Text="{Binding  Path=Alter}" />
  <Button Grid.Column="1" Grid.Row="2" Name="button1"
          Width="100" HorizontalAlignment="Right"
          Click="Erzeugen">Datenerzeugung</Button>
  <Button Grid.Column="1" Grid.Row="3" Name="button2"
          Width="100" HorizontalAlignment="Right"
          Click="Ändern">Datenzugriff</Button>
</Grid>
</Window>

Rheinwerk Computing - Zum Seitenanfang

22.7.3 Auflistungen anbinden topZur vorigen Überschrift

Analog zu den im vorigen Abschnitt beschriebenen Objekten müssen Auflistungen die Schnittstelle INotifyCollectionChanged implementieren. Am einfachsten leiten Sie die generische Klasse System.Collections.ObjectModel.ObservableCollection ab, die die Schnittstelle bereits implementiert.

Wir definieren eine Auflistung, die Person-Objekte des vorigen Abschnitts verwaltet. Alle Personen der Auflistung werden in einer ListBox angezeigt (siehe Abbildung 22.7). Da die Auflistung sofort bei der Instanziierung mit Person-Objekten gefüllt werden soll, leiten wir ObservableCollection ab und erzeugen im Konstruktor Person-Objekte.

Abbildung 22.7 Beispiel für Datenschablonen


'...\WPFKonzepte\Datenbindung\Personenliste.xaml

Imports System.Collections.ObjectModel
Public Class Personenliste : Inherits ObservableCollection(Of Person)
  Public Sub New()
    Add(New Person() With {.Zuname = "Fischer", .Alter = 52})
    Add(New Person() With {.Zuname = "Müller", .Alter = 32})
    Add(New Person() With {.Zuname = "Schmitz", .Alter = 85})
    Add(New Person() With {.Zuname = "Meier", .Alter = 13})
    Add(New Person() With {.Zuname = "Mayer", .Alter = 30})
  End Sub
End Class

In XAML füllen wir die ListBox mittels einer Schablone. Sie definiert eine Zeile, die statt konkreter Daten eine Bindung zur darzustellenden Eigenschaft benutzt. Die Gestaltung der Zeile erfolgt genau so, als stünde sie direkt im Dokument. Eine solche Schablone lässt sich später der ListBox (oder beispielsweise auch einer ComboBox) zuordnen.

DataTemplate beschreibt eine solche Schablone. Sie wird im Ressourcenbereich der XAML-Datei definiert, in dem zudem ein Objekt vom Typ Personenliste erzeugt wird:

<Window.Resources>
  <pers:Personenliste x:Key="Persliste" />
  <DataTemplate x:Key="ItemTemplateName">
    <StackPanel Orientation="Horizontal">
      <TextBlock Text="{Binding Path=Zuname}" />
      <TextBlock Text=" – " />
      <TextBlock Text="{Binding Path=Alter}" />
    </StackPanel>
  </DataTemplate>
</Window.Resources>

Was bleibt, ist die Zuordnung der Ressourcen zu der ListBox. In ItemSource wird die Datenquelle genannt, aus der die Informationen zu beziehen sind. ItemTemplate beschreibt das Muster (DataTemplate), mit dem die in ItemSource spezifizierten Daten angezeigt werden.

<ListBox Name="listbox1" Height="80"
   ItemsSource="{Binding Source={StaticResource Persliste}}"
   ItemTemplate="{StaticResource ItemTemplateName}"  />

Das Fenster enthält noch zwei Buttons. Beim Klicken auf den ersten Button wird das aktuell selektierte Listboxelement aus der Liste gelöscht, mit dem zweiten Button wird ein neues Element hinzugefügt. Hier sehen Sie zunächst den kompletten Code der XAML-Datei:

<Window xmlns:pers="clr-namespace:Datenbindung" ...>
  <Window.Resources>
    <pers:Personenliste x:Key="Persliste" />
    <DataTemplate x:Key="ItemTemplateName">
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Zuname}" />
        <TextBlock Text=" – " />
        <TextBlock Text="{Binding Path=Alter}" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <StackPanel>
    <ListBox Name="listbox1" Height="80"
       ItemsSource="{Binding Source={StaticResource Persliste}}"
       ItemTemplate="{StaticResource ItemTemplateName}"  />
    <StackPanel Orientation="Horizontal">
      <Button Name="btnDelete" Click="Löschen">Person löschen</Button>
      <Button Name="btnAdd" Click="Hinzufügen">Person hinzufügen</Button>
    </StackPanel>
  </StackPanel>
</Window>

Was noch fehlt, ist der Code in den Ereignishandlern der beiden Schaltflächen:

Partial Public Class Liste
  Public liste As Personenliste
  Private Sub Laden(ByVal sender As Object, ByVal e As RoutedEventArgs)
    liste = CType(FindResource("Persliste"), Personenliste)
  End Sub

  Private Sub Löschen(ByVal sender As Object, ByVal e As RoutedEventArgs)
    liste.RemoveAt(listbox1.SelectedIndex)
  End Sub

  Private Sub Hinzufügen(ByVal sender As Object, ByVal e As RoutedEventArgs)
    liste.Add(New Person() With {.Zuname = "Kleinen", .Alter = 45})
  End Sub
End Class



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 Basic 2008
Visual Basic 2008
Jetzt Buch bestellen


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

 Buchempfehlungen
Zum Rheinwerk-Shop: Visual Basic 2012






 Visual Basic 2012


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






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


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






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
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