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

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 21 Datenbindung
Pfeil 21.1 Wichtige Klassen
Pfeil 21.1.1 Die Klasse »Binding«
Pfeil 21.1.2 Die Klasse »DataContext«
Pfeil 21.2 Einfache Datenbindung
Pfeil 21.2.1 Bindung mit Code erzeugen
Pfeil 21.2.2 Bindungsrichtung
Pfeil 21.2.3 Änderung der Datenquelle
Pfeil 21.2.4 Weitere Möglichkeiten im Zusammenhang mit der Datenbindung
Pfeil 21.2.5 Die Ereignisse »SourceUpdated« und »TargetUpdated«
Pfeil 21.3 Verschiedene Datenbindungsquellen
Pfeil 21.3.1 Bindung an einfache Objekte
Pfeil 21.3.2 Auflistungen binden
Pfeil 21.4 DataTemplates festlegen
Pfeil 21.4.1 Trigger
Pfeil 21.5 Daten konvertieren
Pfeil 21.5.1 Beispielprogramm
Pfeil 21.5.2 Mehrfachbindungen und »Converter«-Klassen
Pfeil 21.6 Die Klasse »ObjectDataProvider«
Pfeil 21.7 WPF und ADO.NET
Pfeil 21.7.1 Ausgabe in einer ListBox
Pfeil 21.7.2 Eine Tabelle im DataGrid-Steuerelement
Pfeil 21.7.3 WPF und LINQ to SQL


Galileo Computing - Zum Seitenanfang

21.7 WPF und ADO.NET Zur nächsten ÜberschriftZur vorigen Überschrift


Anmerkung

In diesem Abschnitt werden wir uns mit der Bindung an Daten beschäftigen, die aus einer Datenbank stammen. Das Thema Datenbanken wird uns erst später in diesem Buch begegnen. Möglicherweise werden Ihnen daher einige Klassen und der datenbankspezifische Code noch vollkommen unbekannt sein. Als Autor steht man aber des Öfteren vor dem Problem, den Weg eines thematisch sinnvollen Aufbaus des Buches verlassen zu müssen, weil Themen getriebeartig ineinandergreifen. Sollten Sie mit ADO.NET bzw. Datenbankzugriffen unter .NET ganz allgemein noch keine Erfahrungen haben, sollten Sie mit dem nächsten Kapitel fortfahren und erst später die folgenden Seiten lesen.


In der Praxis werden Sie in der Regel weniger einzelne Objekte oder Listen an Steuerelemente binden. Vielmehr wird es sich eher um Daten aus Datenbanken handeln, die – in unterschiedlicher Form aufbereitet – ihren Weg in die Benutzeroberfläche nehmen. Deshalb sei in diesem letzten Abschnitt des Kapitels anhand einiger Beispiele gezeigt, wie Sie die Daten an die Steuerelemente binden. Dazu werden wir zuerst mit ADO.NET-Objekten arbeiten, anschließend auch noch mit LINQ to SQL.


Galileo Computing - Zum Seitenanfang

21.7.1 Ausgabe in einer ListBox Zur nächsten ÜberschriftZur vorigen Überschrift

Das erste, einfach gehaltene Beispiel soll den Inhalt der Tabelle Products der Northwind-Datenbank in einem ListBox-Steuerelement anzeigen. Angezeigt werden sollen die Inhalte der Spalten ProductName, UnitPrice und UnitsInStock. Um alle drei Angaben in einem Item zusammenzufassen, wird die Angabe eines DataTemplate notwendig sein. Das Ergebnis zur Laufzeit sehen Sie in Abbildung 21.6.

Lassen Sie uns zuerst die Daten bereitstellen. Das ist im Grunde genommen sehr simpel: Wir besorgen uns zuerst das DataSet und binden dieses an den Datenkontext der ListBox:


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 21\WPF_ADOSample1
// ---------------------------------------------------------
public MainWindow() {
  InitializeComponent();
  SqlConnection con = new SqlConnection( @"...");
  SqlCommand cmd = new SqlCommand(
          "SELECT ProductName, UnitPrice, UnitsInStock FROM Products", con);
  DataSet ds = new DataSet();
  SqlDataAdapter da = new SqlDataAdapter(cmd);
  da.Fill(ds);
  listBox1.DataContext = ds;
}

Abbildung 21.6 Ausgabe des Beispiels »WPF_ADOSample1«

Sehen wir uns nun den XAML-Code an:


<Window ...>
  <Window.Resources>
    <DataTemplate x:Key="listBoxTemplate">
      <StackPanel Margin="3">
        <DockPanel>
          <TextBlock Text="Artikel:" DockPanel.Dock="Left" 
                     Margin="5,0,10,0"/>
          <TextBlock Text="             " />
          <TextBlock Text="{Binding ProductName}" 
                     Foreground="Blue" FontWeight="Bold" />
        </DockPanel>
        <DockPanel>
          <TextBlock Text="Preis:" DockPanel.Dock="Left" Margin="5,0,5,0"/>
          <TextBlock Text="                 " />
          <TextBlock Text="{Binding UnitPrice}"  FontWeight="Bold" />
        </DockPanel>
        <DockPanel>
          <TextBlock Text="Lagerbestand:" DockPanel.Dock="Left" 
                     Margin="5,0,5,0"/>
          <TextBlock Text="   " />
          <TextBlock Text="{Binding UnitsInStock}" FontWeight="Bold" />
        </DockPanel>
        <DockPanel>
          <TextBlock Text="----------------------------------------------"/>
        </DockPanel>
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <ListBox Margin="17,8,15,26" Name="listBox1"  
             ItemsSource="{Binding Tables[0]}" 
             ItemTemplate="{StaticResource listBoxTemplate}" />
  </Grid>
</Window>

Die ListBox müssen wir mit der Eigenschaft ItemSource an die Datenquelle binden. Dabei wird die Tabelle im DataSet angegeben:


ItemsSource="{Binding Tables[0]}"

Sie können dem Datenkontext auch direkt die gewünschte Tabelle übergeben und müssen dann nur die Bindung von ItemSource an den Datenkontext beschreiben:


listBox1.DataContext = ds.Tables[0];
...
ItemsSource="{Binding}"

Jeder Listeneintrag eines Produkts wird durch ein StackPanel in DataTemplate beschrieben. Da wir mit jedem Listeneintrag auch drei Ausgabezeilen produzieren wollen, wird jede Zeile durch ein DockPanel beschrieben, das in sich wieder drei TextBlock-Elemente hat. Das TextBlock-Element, das entweder den Produktbezeichner, den Preis oder den Lagerbestand anzeigen soll, binden wir an die entsprechende Spalte der gebundenen Tabelle, z. B. so:


<TextBlock Text="{Binding ProductName}"


Galileo Computing - Zum Seitenanfang

21.7.2 Eine Tabelle im DataGrid-Steuerelement Zur nächsten ÜberschriftZur vorigen Überschrift

Bindung des DataGrid

Tabellensteuerelemente gehören sicherlich zu den am häufigsten eingesetzten Controls in grafischen Benutzeroberflächen. Mit Einführung von Visual Studio 2008 und dem .NET-Framework 3.5 waren viele Entwickler überrascht, dass Microsoft für die WPF ein solches Steuerelement nicht vorgesehen hatte. Nur Drittanbieter oder das später veröffentlichte WPF-Toolkit konnten diese Lücke füllen.

In Visual Studio 2010 wird nun ein WPF-Tabellensteuerelement standardmäßig angeboten. Wie nicht anders zu erwarten, glänzt dieses Steuerelement durch zahllose Eigenschaften, die zusammen mit den WPF-typischen Möglichkeiten nur noch wenige Wünsche offenlassen (zumindest so weit diese nicht ganz spezifischer Natur sind).

Es ist sehr einfach, das DataGrid-Control mit einer ADO.NET-Datenquelle zu verbinden. Sie übergeben das DataSet der Eigenschaft DataContext entweder des Windows oder des DataGrids, zum Beispiel:


public MainWindow() {
  InitializeComponent();
  ...
  da.Fill(ds, "Orders");
  this.DataContext = ds;
}

Die Variable da beschreibt den DataAdapter, und ds beschreibt das DataSet.

Da ein DataGrid zu den Listensteuerelementen zählt, wird mit der Eigenschaft ItemSource die Bindung an die Datenquelle beschrieben. Mit der Eigenschaft AutoGenerateColumns legen Sie fest, ob die Spalten automatisch erzeugt werden sollen. Im einfachsten Fall können Sie hier true angeben, den Rest erledigt das Steuerelement selbst.


<DataGrid ItemsSource="{Binding Orders}" 
          AutoGenerateColumns="true" HorizontalAlignment="Left"  
          Name="dataGrid1"/>

In Abbildung 21.7 sehen Sie die Ausgabe des Fensters zur Laufzeit.

Abbildung 21.7 Das DataGrid-Steuerelement

Spalten modifizieren

Wenn Sie die Eigenschaft AutoGenerateColumns auf false festlegen, müssen Sie selbst für die Anzeige der Spalten sorgen. Was sich im ersten Moment nach unnötigem Codierungsaufwand anhört, eröffnet weitreichende Möglichkeiten in der individuellen Gestaltung der einzelnen Spalten.

Per Vorgabe werden alle Spalte als reine Textspalten angezeigt. Daneben werden auch Spalten vom Typ Hyperlink, CheckBox und ComboBox angeboten, beschrieben durch die Klassen DataGridHyperlinkColumn, DataGridCheckBoxColumn und DataGridComboBoxColumn. Sollte Ihnen auch das noch nicht ausreichen, können Sie mit DataGridTemplateColumn auch eigene Spaltentypen definieren. DataGridTemplateColumn ermöglicht es mit seinen Eigenschaften CellTemplate und CellEditingTemplate sogar, Templates für den Anzeige- und Änderungszustand bereitzustellen.

Damit ist noch nicht alles beschrieben. Mit der Eigenschaft RowsDetailsTemplate kann unterhalb der ausgewählten Datenzeile ein Bereich geöffnet werden, der beliebige Informationen beinhalten kann (siehe Abbildung 21.8).

Wir wollen uns auch sofort das Beispielprogramm ansehen, das zu der Ausgabe des Fensters in Abbildung 21.8 führt. Dabei gehen wir noch einen Schritt weiter und machen uns zur Aufgabe, in der Spalte Lieferdatum im Editiermodus das Steuerelement DatePicker einzublenden (siehe Abbildung 21.9).

Abbildung 21.8 DataGrid mit Detailbereich

Abbildung 21.9 Das DatePicker-Steuerelement zum Editieren

Per Vorgabe wird danach neben dem Datum auch die Uhrzeit angezeigt. Da uns die Uhrzeit allerdings bei der Anzeige des Lieferdatums nicht interessiert, soll ein Konverter bereitgestellt werden, der die Uhrzeit ausblendet.


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 21\WPF_ADOSample2
// ---------------------------------------------------------
<Window ... xmlns:local="clr-namespace:WPF_ADOSample2">    
<Window.Resources>
   <local:DateConverter x:Key="dateConverter"></local:DateConverter>
</Window.Resources>
<StackPanel>
  <DataGrid ItemsSource="{Binding Orders}" AutoGenerateColumns="False" 
            Name="dataGrid1" SelectionChanged="dataGrid1_SelectionChanged" 
            AlternatingRowBackground="#FFBBF0D1">
    <DataGrid.RowDetailsTemplate>
      <DataTemplate>
        <StackPanel>
          <TextBlock Text="BestellNr.:"/>
          <TextBlock Text="  "/>
          <TextBlock Text="{Binding OrderID}" />
          <TextBlock Text="  "/>
          <TextBlock Text="{Binding ShipPostalCode}"/>
          <TextBlock Text="  "/>
          <TextBlock Text="{Binding ShipCity}"/>
        </StackPanel>
      </DataTemplate>
    </DataGrid.RowDetailsTemplate>
    <DataGrid.Columns>            
      <DataGridTextColumn Header="Bestell-Nr." Binding="{Binding OrderID}"/>
      <DataGridTemplateColumn Header="Lieferdatum">
        <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate>
            <DatePicker SelectedDate="{Binding ShippedDate}" />
          </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>
        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBlock Text="{Binding Path=ShippedDate,
                       ConverterCulture=de-DE, 
                       Converter={StaticResource dateConverter}}" />
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>      
      <DataGridTextColumn Header="Adresse" 
                          Binding="{Binding ShipAddress}" /> 
      <DataGridTextColumn Header="Stadt" Binding="{Binding ShipCity}" />
      <DataGridTextColumn Header="Postleitzahl" 
                          Binding="{Binding ShipPostalCode}" />
      <DataGridTextColumn Header="Land" 
                          Binding="{Binding ShipCountry}" />
    </DataGrid.Columns>
  </DataGrid>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="150" />
      <ColumnDefinition Width="150" />
      <ColumnDefinition Width="150" />
    </Grid.ColumnDefinitions>
     <Button Name="btnUpdate" Click="btnUpdate_Click" Content="Speichern" />
  </Grid>
</StackPanel>
</Window>

Der XAML-Code wurde hier um die Layout-Eigenschaftseinstellungen gekürzt, die im Zusammenhang mit der Datenbindung unwichtig sind.

Betrachten wir nun einzelne Passagen im Detail. Mit


<DataGridTemplateColumn.CellEditingTemplate>
  <DataTemplate>
    <DatePicker SelectedDate="{Binding ShippedDate}" />
  </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

wird die Spalte Lieferdatum im Editiermodus beschrieben. Definiert wird dieser durch ein DataTemplate, das an die Eigenschaft CellEditingTemplate übergeben wird und ein DatePicker-Control anzeigt. Der Anwender kann aus dem Control ein anderes Datum auswählen.

Die Eigenschaft CellTemplate des DataGridTemplateColumn-Objekts steht für den Anzeigemodus der Spalte Lieferdatum.


<DataGridTemplateColumn.CellTemplate>
  <DataTemplate>
    <TextBlock Text="{Binding Path=ShippedDate,
               ConverterCulture=de-DE, 
               Converter={StaticResource dateConverter}}" />
  </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Innerhalb des Templates stellen wir mit der Eigenschaft ConverterCulture sicher, dass für die Anzeige des Datums das übliche deutsche Format verwendet wird. Hat der Benutzer aus dem DatePicker-Steuerelement ein anderes Datum ausgewählt, würde dieses zusammen mit der Uhrzeit angezeigt. Da die Uhrzeit nicht interessiert, filtern wir sie mit dem Converter dateConverter heraus. Die Klasse des Converters ist folgendermaßen codiert:


class DateConverter : IValueConverter {
  public object Convert(object value, Type targetType, object parameter, 
                        System.Globalization.CultureInfo culture)
  {
    return ((DateTime)value).ToShortDateString();
  }
  public object ConvertBack(object value, Type targetType, object parameter, 
                            System.Globalization.CultureInfo culture)
  {
    return DateTime.Parse(value.ToString());
  }
}

Die Converter-Klasse ist im Resources-Abschnitt des Window eingetragen.

Kommen wir zum nächsten interessanten Teilbereich des XAML-Codings: dem Detailbereich der ausgewählten Datenzeile im DataGrid. Dieser wird durch die Eigenschaft RowDetailsTemplate des Tabellensteuerelements beschrieben, in der ein DataTemplate eingebettet ist.


<DataGrid.RowDetailsTemplate>
  <DataTemplate>
    <StackPanel>
      <TextBlock Text="BestellNr.:"/>
      <TextBlock Text="  "/>
      <TextBlock Text="{Binding OrderID}" />
         ...
      </StackPanel>
    </DataTemplate>
 </DataGrid.RowDetailsTemplate>

Es bleibt natürlich Ihnen überlassen, wie Sie diesen Bereich darstellen. In unserem Beispiel werden nur einige Informationen der ausgewählten Datenzeile im Großformat angezeigt.

Zum Schluss bleibt uns noch, einen Blick in den Code-Behind zu werfen. Im Konstruktor wird die Verbindung zur Datenbank aufgebaut und das DataSet gefüllt. Eine Schaltfläche im Window gestattet es uns, die Änderungen in die Datenbank zu schreiben. Es genügt hierzu der Aufruf der Methode Update des SqlDataAdapters.

Um zu zeigen, wie Sie auf den Inhalt einer bestimmten Zelle des selektierten Datensatzes zugreifen können, wurde das Ereignis SelectionChanged des DataGrids programmiert. Das Ereignis wird immer dann ausgelöst, wenn sich die Datenzeilenauswahl ändert. Der Ereignishandler benutzt das Ereignis, um die Bestellnummer in die Titelleiste des Window einzutragen.


private void btnUpdate_Click(object sender, RoutedEventArgs e) {
  da.Update(ds, "Orders");
}
private void dataGrid1_SelectionChanged(object sender, 
             SelectionChangedEventArgs e) {
  string orderID = 
         ((DataRowView)dataGrid1.SelectedItem)["OrderID"].ToString();
  this.Title = "Bestell-Nr.: " + orderID;
}


Galileo Computing - Zum Seitenanfang

21.7.3 WPF und LINQ to SQL topZur vorigen Überschrift

Das letzte Beispiel, mit dem ich Ihnen die Datenbindung unter WPF zeigen möchte, ist ein Beispiel, bei dem LINQ to SQL zum Einsatz kommt. Das Beispiel ist sehr einfach gehalten und glänzt mehr durch sein farbenfrohes Layout als durch besondere Finessen.

Es werden einfach nur die Kunden abgefragt, die in Deutschland wohnen. Angezeigt wird das Resultat der Abfrage in einem ListView-Steuerelement.


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 21\WPF_LINQ_To_SQL
// ---------------------------------------------------------
public MainWindow() {
  InitializeComponent();
  NorthwindDataContext db = new NorthwindDataContext();
  var customers = from c in db.Customers
                  where c.Country == "Germany"
                  select c;
  listView1.ItemsSource = customers;
}

Dazu noch der XAML-Code:


<Window ... >
  <Window.Resources>
    <DataTemplate x:Key="ShowCustomer">
      <StackPanel Orientation="Horizontal">
        <StackPanel Margin="10">
          <TextBlock Text="{Binding ContactName}" FontWeight="Bold"/>
          <TextBlock Text="{Binding ContactTitle}" FontStyle="Italic"/>
          <TextBlock Text="{Binding ContactName}"/>
        </StackPanel>
      </StackPanel>
    </DataTemplate>
  </Window.Resources>
  <ScrollViewer>
    <DockPanel>
      <ListView Name="listView1" 
                ItemTemplate="{StaticResource ShowCustomer}">
        <ListView.Background>
          <RadialGradientBrush>
            <GradientStop Color="Aqua"  Offset="0"/>
            <GradientStop Color="Bisque" Offset="1"/>
          </RadialGradientBrush>
        </ListView.Background>
      </ListView>
    </DockPanel>
  </ScrollViewer>
</Window>

Abbildung 21.10 Ausgabe des Beispielprogramms »WPF_LINQ_to_SQL«



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# 2010

Visual C# 2010
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 2010
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