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 25 Weitere Möglichkeiten der Datenbindung
Pfeil 25.1 »ItemsControl«-Steuerelemente anpassen
Pfeil 25.1.1 Den Style eines »ListBoxItem«-Elements ändern
Pfeil 25.1.2 DataTemplates festlegen
Pfeil 25.1.3 »DataTemplates« mit Trigger
Pfeil 25.2 Alternative Datenbindungen
Pfeil 25.2.1 Die Klasse »ObjectDataProvider«
Pfeil 25.3 Navigieren, Filtern, Sortieren und Gruppieren
Pfeil 25.3.1 Navigieren
Pfeil 25.3.2 Sortieren
Pfeil 25.3.3 Filtern
Pfeil 25.3.4 Gruppieren
Pfeil 25.4 Das Steuerelement »DataGrid«
Pfeil 25.4.1 Elementare Eigenschaften des »DataGrid«
Pfeil 25.4.2 Spalten definieren
Pfeil 25.4.3 Details einer Zeile anzeigen

25 Weitere Möglichkeiten der DatenbindungZur nächsten Überschrift

Die einfache Datenbindung war das Thema des letzten Kapitels. Meistens werden aber Datenquellen gebunden, die viele Elemente enthalten: Tabellen einer Datenbank beispielsweise oder auch nur einfache Collections. Die Elemente werden meistens bevorzugt in Steuerelementen angezeigt, die dem Benutzer mehr als nur einen Datensatz oder ein Listenelement anzeigen. Hier kommen die WPF-ItemsControls ins Spiel, Steuerelemente also, die von der Basis ItemsControl abgeleitet sind. Die WPF hat einige davon zu bieten:

  • ComboBox
  • ListBox
  • ListView
  • TabControl
  • ToolBar
  • Menu
  • MenuItem
  • TreeViewItem
  • ContextMenu
  • StatusBar

Diese Steuerelemente können mit der Eigenschaft DataContext oder alternativ mit der Eigenschaft ItemsSource an eine Datenquelle gebunden werden. Die Fähigkeiten gehen aber noch weiter, denn mit DataTemplates lässt sich auch die Darstellung jedes einzelnen Items innerhalb der Controls nahezu beliebig an eigene Vorstellungen anpassen. Zudem wird jede auf einer – ganz allgemein gesagt – Liste basierende Datenquelle von der WPF automatisch in einen View gepackt, um die Navigation, Sortierung, Filterung und Gruppierung der Daten zu ermöglichen. Das sind die Themen, denen wir uns in diesem Kapitel schwerpunktmäßig widmen.


Galileo Computing - Zum Seitenanfang

25.1 »ItemsControl«-Steuerelemente anpassenZur nächsten ÜberschriftZur vorigen Überschrift

Alle von der Basis ItemsControl abgeleiteten Klassen unterstützen auf zweierlei Art und Weise die Anpassung des Layouts der anzuzeigenden Daten:

  • Styles
  • DataTemplates

Styles sind nur mit elementaren Möglichkeiten ausgestattet und stellen ein einfaches, aber auch limitiertes Hilfsmittel zur Gestaltung des Layouts eines Listeneintrags dar. Denken wir exemplarisch an eine ListBox. Die angezeigten Elemente einer ListBox sind vom Typ ListBoxItem und können mit einem Style in ihrem Aussehen beeinflusst werden. Beispielsweise ließe sich die Hintergrundfarbe ändern oder eine andere Schriftart festlegen. Aber es bleiben immer ListBoxItem-Elemente, die darüber hinaus auch nur eine einzige Bindung beschreiben können.

Mit einem DataTemplate unterliegen Sie keiner Einschränkung. DataTemplates ermöglichen die Bindung an mehrere Eigenschaften eines Datenquellenelements und gestatten es, dem Item eines ItemsControls durch eine beliebige Kombination mehrerer WPF-Elemente das Layout zu geben, das Sie sich vorstellen.

Zu diesem Zweck stellt die Klasse ItemsControl den abgeleiteten Klassen zahlreiche Eigenschaften zur Verfügung. Sie können einige davon der folgenden Tabelle entnehmen. Diese Eigenschaften – neben zahlreichen anderen – werden auch im Verlauf des Kapitels in den Beispielen konkret gezeigt.

Tabelle 25.1 Eigenschaften eines »ItemsControl«-Steuerelements

Eigenschaft Beschreibung

AlternationCount

Mit dieser Eigenschaft lassen sich die einzelnen Elemente in einem ItemsControl unterschiedlich darstellen.

DisplayMemberPath

Diese Property gibt die Eigenschaft des Elements an, die zur Anzeige im Steuerelement verwendet wird.

GroupStyle

Diese Eigenschaft definiert einen Style, der zum Gruppieren von
Elementen verwendet wird.

ItemContainerStyle

Diese Eigenschaft definiert den Style jedes einzelnen Elements.

ItemsSource

Beschreibt eine Menge von Elementen, die in diesem Steuerelement zur Anzeige verwendet wird. Der ItemsSource-Eigenschaft können nur Objekte vom Typ IEnumerable zugewiesen werden.

ItemTemplate

Diese Eigenschaft definiert das DataTemplate für die im Steuerelement enthaltenen Elemente.


Galileo Computing - Zum Seitenanfang

25.1.1 Den Style eines »ListBoxItem«-Elements ändernZur nächsten ÜberschriftZur vorigen Überschrift

Wir wollen uns als Erstes ansehen, wie wir den Stil eines ListBoxItem-Elements beeinflussen können. Dazu greifen wir auf das Beispielprogramm ListBoxBindingSample zurück, das wir uns in Kapitel 24 angesehen haben (siehe auch Abbildung 24.2).

Unser Ziel sei es, die Darstellung der ListBox-Einträge ansprechender zu gestalten. Dazu soll jeder Eintrag eine individuelle, alternierende Hintergrundfarbe erhalten und mit einer grauen Umrandung angezeigt werden. Das aktuell ausgewählte ListBox-Element soll ebenfalls einen eigenen Stil haben und farblich abgesetzt von den anderen erkennbar sein. Hier zunächst der XAML-Code, um den der bisherige ergänzt werden muss.

// Beispiel: ..\Kapitel 25\ItemContainerStyleSample

<ListBox Name="listBox1" Margin="10" AlternationCount="2">
<ListBox.ItemContainerStyle>

<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="AntiqueWhite" />
<Setter Property="Margin" Value="1"></Setter>
<Setter Property="Padding" Value="1"></Setter>
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="LightGreen" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Listing 25.1 XAML-Code des Beispielprogramms »ItemContainerStyleSample«

Abbildung

Abbildung 25.1 Laufzeitdarstellung des Beispiels »ItemContainerStyleSample«

Der Style der einzelnen ListBox-Einträge wird durch die Eigenschaft ItemContainerStyle beschrieben. Innerhalb des Style-Abschnitts beschreibt der erste Abschnitt ein »normales« Listenelement (Standardschablone). Die WPF unterstützt für alternierende Einträge zwei Eigenschaften: AlternationCount und AlternationIndex. AlternationCount gibt an, wie viele Listeneinträge eine Gruppe bilden sollen. In unserem Beispiel handelt es sich um zwei. Per Vorgabe ist AlternationCount auf »0« eingestellt.

Jedem ListBoxItem ist ein AlternationIndex zugeordnet, der die Position innerhalb der Gruppe angibt. Für alle Elemente, die von der Listenposition »0« abweichen, muss ein eigener Trigger bereitgestellt werden, der AlternationIndex angibt und die Darstellung der entsprechend indizierten Einträge beschreibt.

Nehmen wir beispielsweise an, wir hätten eine ListBox mit der Einstellung AlternationCount=3. Dann würde dem ersten Listenelement die Standardschablone zugewiesen, dem zweiten Element die Schablone mit AlternationIndex=1, dem dritten die mit AlternationIndex=2. Das vierte Element schließlich wird wieder in der Standardschablone dargestellt.

Sie müssen berücksichtigen, dass AlternationIndex eine angehängte Eigenschaft ist, die in der ListBox definiert ist. Daher muss im Trigger der Klassenname mit

Property="ItemsControl.AlternationIndex"

spezifiziert werden.


Galileo Computing - Zum Seitenanfang

25.1.2 DataTemplates festlegenZur nächsten ÜberschriftZur vorigen Überschrift

In der ListBox des vorhergehenden Beispiels wird nur der Name angezeigt. Im Grunde genommen erstaunt das nicht, denn woher soll die ListBox auch wissen, welche Darstellungsform der Anzeige wir uns wünschen. Die ListBox reagiert nur auf die Angabe, die wir unter der Eigenschaft DisplayMemberPath gemacht haben. Diese Eigenschaft selbst erlaubt keine komplexeren Darstellungsmöglichkeiten.

DataTemplates schaffen hier Abhilfe. Sie gestatten es, die Inhalte und deren Darstellung exakt festzulegen. Damit wird es uns möglich, nicht nur mehrere Inhalte in einer Zeile auszugeben. Wir können darüber hinaus auch in jeder anderen Weise die Darstellung manipulieren, beispielsweise durch alternierende Farben. DataTemplates ähneln den ControlTemplates. Sie können Sie im Window.Resources-Abschnitt festlegen und die Darstellung der Daten ähnlich beschreiben, wie Sie auch einem Steuerelement mit einem ControlTemplate zu einer anderen Darstellung verhelfen.

Es werden in Abhängigkeit vom Typ des Steuerelements zwei Datenschablonen unterschieden:

  • ContentTemplate dient als Vorlage eines Content-Steuerelements.
  • DataTemplate dient als Datenvorlage aller Steuerelemente, die von ItemsControl abgeleitet sind.

Mit einem DataTemplate ist es möglich, ein Listenelement auch komplex durch mehrere WPF-Elemente anzuzeigen. Denken wir dazu noch einmal an die Klasse Person, die die Eigenschaften Name, Alter und Adresse beschreibt. In einer ListBox wird ein Item genau die Eigenschaft anzeigen, die durch die Eigenschaft DisplayMemberPath beschrieben wird. Mit einem DataTemplate lässt sich ein Item der ListBox beschreiben, in dem sich möglicherweise alle Eigenschaften wiederfinden.

Der folgende XAML-Code zeigt ein DataTemplate, um in einem ItemsControl-Element neben dem Namen der Person auch deren Alter und Adresse auszugeben. Beachten Sie die Angabe des Datenobjekts mit DataType als Eigenschaft des DataTemplate-Elements. Damit wird zum Ausdruck gebracht, dass Person-Objekte durch diese Schablone beschrieben werden.

// Beispiel: ..\Kapitel 25\ListBoxWithDataTemplate

<Window.Resources>
<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:Person}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Width="100" Grid.Column="0"
Text="{Binding Path=Name}"/>
<TextBlock Width="30" Grid.Column="1"
Text="{Binding Path=Alter}"/>
<TextBlock Width="30" Grid.Column="2"
Text="{Binding Path=Adresse}"/>
</Grid>
</DataTemplate>
</Window.Resources>

Listing 25.2 Ein einfaches »DataTemplate«-Beispiel

In diesem DataTemplate wird für ein Person-Item ein Grid mit drei Spalten verwendet, in denen die drei Eigenschaften einer Person in jeweils einem TextBlock ausgegeben werden. Jeder TextBlock ist an eine Person-Eigenschaft gebunden und bezieht die Daten aus dem jeweiligen Item.

Eine Anpassung des ItemsControl-Elements ist ebenfalls notwendig. Es benötigt nicht mehr die Angabe der Eigenschaft DisplayMemberPath, sondern erwartet in seiner Eigenschaft ItemTemplate den Key der Ressource des DataTemplate.

<ListBox Grid.Column="0" Name="lstPersonen"
ItemTemplate="{StaticResource PersonTemplate}" />

Listing 25.3 Anbindung des »DataTemplate«

In Abbildung 25.2 sehen Sie, wie die ListBox unter Zuhilfenahme des DataTemplate die Elemente anzeigt.

Abbildung

Abbildung 25.2 ListBox mit »DataTemplate«

Die Schablone lässt sich auch direkt im Steuerelement angeben. Hierfür wird die Eigenschaft ItemTemplate bereitgestellt, in die das DataTemplate eingebettet wird.

<ListBox Grid.Column="0" Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:Person}">
<Grid>
[...]
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Listing 25.4 »DataTemplate« innerhalb eines Elements

Der Nachteil im Vergleich zu einem im Resource-Abschnitt definierten DataTemplate ist, dass dieses DataTemplate nicht von anderen Steuerelementen genutzt werden kann.


Galileo Computing - Zum Seitenanfang

25.1.3 »DataTemplates« mit TriggerZur vorigen Überschrift

Vorlagen können mit Trigger ausgestattet werden. Das gilt nicht nur für ContentTemplate, sondern auch für DataTemplate. Trigger gestatten es einem Template, auf Veränderungen von Daten zu reagieren und die Darstellung anzupassen. Definieren Sie einen herkömmlichen Trigger, kann dieser nur auf die Veränderung des Steuerelements selbst reagieren. Um auf eine Veränderung der Datenquelle reagieren zu können, stellt die WPF zwei Klassen bereit:

  • DataTrigger
  • MultiDataTrigger

DataTrigger arbeiten mit der Datenbindung. Sie können eine beliebige Eigenschaft des Objekts abfragen, um unter bestimmten Umständen auf deren Wert zu reagieren. Das sei am Beispiel der Klasse Person gezeigt. Dabei sollen die Person-Objekte, die das Rentenalter erreicht oder überschritten haben, in der ListBox mit rotem Hintergrund dargestellt werden. Aus diesem Grund erweitern wir die Klasse Person um die Eigenschaft Rente. Zudem muss auch die Eigenschaft Alter ergänzt werden um eine Überprüfung im set-Zweig, ob das neue Alter die Altersgrenze überschreitet.

public class Person : INotifyPropertyChanged {
private bool _Rente;
public bool Rente {
get { return _Rente; }

private set {
_Rente = value;
OnPropertyChanged(new PropertyChangedEventArgs("Rente"));
}
}
private int? _Alter;
public int? Alter
{
get { return _Alter; }
set {
_Alter = value;
if (Alter >= 65) Rente = true;
else Rente = false;
OnPropertyChanged(new PropertyChangedEventArgs("Alter"));
}
}
[...]
}

Listing 25.5 Änderungen an der Klasse »Person«

Auch das DataTemplate muss angepasst werden, da eine Ergänzung um die Festlegung der Eigenschaft DataTemplate.DataTriggers erforderlich ist, innerhalb deren der Trigger definiert wird.

// Beispiel: ..\Kapitel 25\DataTriggerSample

<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:Person}">
<Grid Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Width="100" Grid.Column="0" Text="{Binding Path=Name}"/>
<TextBlock Width="30" Grid.Column="1" Text="{Binding Path=Alter}"/>
<TextBlock Width="100" Grid.Column="2" Text="{Binding Path=Adresse}"/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Rente}" Value="True">
<Setter Property="Background" Value="Red" TargetName="grid1" />
</DataTrigger>
</DataTemplate.Triggers>

</DataTemplate>

Listing 25.6 Ergänzung des XAML-Codes um einen »DataTrigger«

Nun wollen wir noch die Möglichkeiten für den Anwender erweitern. Er soll zur Laufzeit eine neue Person zur Liste hinzufügen, das Alter ändern oder die in der ListBox aktuell ausgewählte Person löschen können. Dazu ergänzen wir das Window um drei Schaltflächen, die alle auf das Ereignis Click reagieren sollen und entsprechende Änderungen an der Liste vornehmen. Die Ansicht des Fensters zur Laufzeit sehen Sie in Abbildung 25.3.

Abbildung

Abbildung 25.3 Erweitertes Window mit »DataTrigger«

<Window ...
xmlns:local="clr-namespace:DataTriggerSample">
<Window.Resources>
<Style x:Key="style1">
[...]
</Style>
<DataTemplate x:Key="PersonTemplate" DataType="{x:Type local:Person}">
[...]
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Rente}" Value="True">
<Setter Property="Background" Value="Red" TargetName="grid1" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox Name="listBox1" Margin="10"
ItemTemplate="{StaticResource PersonTemplate}">
</ListBox >
<Grid Grid.Column="1" Margin="5"
DataContext="{Binding ElementName=listBox1, Path=SelectedItem}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
[...]
<Label Style="{StaticResource style1}">Name:</Label>
<Label Style="{StaticResource style1}" Grid.Row="1">Alter:</Label>
<Label Style="{StaticResource style1}" Grid.Row="2">Adresse:</Label>
<TextBox Grid.Column="1" Grid.Row="0" Margin="3"
Text="{Binding Path=Name}/">
<TextBox Grid.Column="1" Grid.Row="1" Margin="3"
Text="{Binding Path=Alter}" />
<TextBox Grid.Column="1" Grid.Row="2" Margin="3"
Text="{Binding Path=Adresse}" />
<Button Name="btnAdd" Grid.Column="1" Grid.Row="3" Margin="3"
Click="btnAdd_Click">Hinzufügen</Button>
<Button Name="btnEditAge" Grid.Column="1" Grid.Row="4" Margin="3"
Click="btnEditAge_Click">Alter ändern</Button>
<Button Name="btnDelete" Grid.Column="1" Grid.Row="5" Margin="3"
Click="btnDelete_Click">Löschen</Button>
</Grid>
</Grid>
</Window>

Listing 25.7 Der XAML-Code des Beispielprogramms »DataTriggerSample«

Was natürlich noch fehlt, sind die drei Ereignishandler für die Schaltflächen. Der Code ist sehr einfach gehalten und gestattet nur statische Änderungen beim Hinzufügen und der Altersänderung. Es ist aber kein großes Problem, auch hier zuerst die Daten beim Benutzer abzufragen.

private void btnAdd_Click(object sender, RoutedEventArgs e) {
liste.Add(new Person { Name = "Walter", Alter = 74,
Adresse = "München" });
}

private void btnEditAge_Click(object sender, RoutedEventArgs e) {
((Person)listBox1.SelectedItem).Alter = 69;
}

private void btnDelete_Click(object sender, RoutedEventArgs e) {
liste.Remove((Person)listBox1.SelectedItem);
}

Listing 25.8 Der C#-Code der Ereignishandler im Beispiel »DataTriggerSample«



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