BlackCoin's Corner

In diesem Blog dreht es sich zu 90 % um den Themenbereich C# .Net

Datenquelle in Registern Visualisieren (Korrektur)

Die heutige Aufgabe:

Wie Visualisiere ich mehre Items einer Xml-Datenquelle, (kann natürlich auch für andere Datenquellen benutzt werden)  mittels WPF, in einer Register Darstellung.

Die Datenquelle besteht in diesem Beispiel, aus 100 zufällig ausgesuchten Datensätzen, der AdventureWorksCinema Sample DB.

an die Datenschützer unter euch, das sind Dummy Datensätze, Ähnlichkeiten mit der Realität wären reiner Zufall!

Nachdem man sich ein neues WPF Projekt erzeugt hat, fügt man als erstes die unten angehängt XML-Datenquellen, in das neue Projekt ein. (nicht vergessen in den Datei Eigenschaften ‘Copy To Output Directory’ auf zb ‘Copy if newer’ umzustellen)

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <XmlDataProvider x:Key="Contacts" Source="Contact.xml" XPath="contacts/ContactItem"/>
  </Window.Resources>
  <Grid>
    <ListView DataContext="{StaticResource Contacts}" ItemsSource="{Binding}">
      <ListView.View>
        <GridView>
          <GridViewColumn Header="Vorname" DisplayMemberBinding="{Binding XPath=FirstName}"/>
          <GridViewColumn Header="Nachname" DisplayMemberBinding="{Binding XPath=LastName}"/>
          <GridViewColumn Header="Telefon" DisplayMemberBinding="{Binding XPath=Phone}"/>
          <GridViewColumn Header="Email" DisplayMemberBinding="{Binding XPath=EmailAddress}"/>
        </GridView>
      </ListView.View>
    </ListView>
  </Grid>
</Window>

Der XmlDataProvider stellt die Daten, aus der XML-Datei, dem Window in seinen Resources zur Verfügung.Da es einfacher ist früh die Fehler zu erkennen, als später unter umständen, aufwendige Fehlersuchen bei den Grundlagen zu betreiben, habe ich an dieser Stelle schnell ein ListView mit Implementiert.

Soweit so gut, um die Datensätze zu Gruppieren nehme ich eine CollectionViewSource

  <Window.Resources>
    <XmlDataProvider x:Key="data" Source="Contact.xml" XPath="contacts/ContactItem"/>

    <CollectionViewSource x:Key="cvs" Source="{StaticResource data}">
      <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="LastName" Converter="{StaticResource firstLetter}"/>
      </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
  </Window.Resources>

Aktuell würden die Datenquellle anhand des Propperties Nachname Gruppiert werden, jedoch ist dies noch nicht ganz das was ich möchte. Ich könnte mir, eher eine Gruppierung, des ersten Buchstaben vom Nachnamens vorstellen. Zum Glück bietet die PropertyGroupDescription ein Property Namens Converter und der passende Converter ist schnell Implementiert.

using System;using System.Windows.Data;

namespace WpfApplication1
{
    public class FirstLetter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value.ToString().Substring(0, 1);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Ich hätte zwar gerne einen SubStringConverter gehabt, jedoch suche ich noch ein Weg, dem Converter in dieser Konstellation ein Parameter mitzugeben. (Wer den Weg kennt, immer her damit, da unten sollte irgendwo ein Kommentarfeld sein, wer es findet darf etwas schreiben)

Die Datensätze werden nun nach dem ersten Buchstaben des Nachnamens gruppiert, jetzt brauche ich nur ein Steuerelement das mir das ganze anzeigt. Ich probiere es mal mit einem TabControl.

 





<TabControl DataContext="{StaticResource cvs}" ItemsSource="{Binding Path=Groups}">
  <TabControl.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Path=Name}"/>
      </StackPanel>
    </DataTemplate>
  </TabControl.ItemTemplate>
</TabControl>

Die Items in jedem Tab, Visualisieren wir die einzelnen Daten im am ende in ein (nein, sagen ich mal besser in n) ListView’s.

 



<Grid>
  <TabControl DataContext="{StaticResource cvs}" ItemsSource="{Binding Path=Groups}">
    <TabControl.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Path=Name}"/>
        </StackPanel>
      </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
      <DataTemplate>
        <ListView ItemsSource="{Binding Items}">
          <ListView.View>
            <GridView>
              <GridViewColumn Header="Vorname" DisplayMemberBinding="{Binding XPath=FirstName}"/>
              <GridViewColumn Header="Nachame" DisplayMemberBinding="{Binding XPath=LastName}"/>
              <GridViewColumn Header="Telefon" DisplayMemberBinding="{Binding XPath=Phone}"/>
              <GridViewColumn Header="Email" DisplayMemberBinding="{Binding XPath=EmailAddress}"/>
            </GridView>
          </ListView.View>
        </ListView>
      </DataTemplate>
    </TabControl.ContentTemplate>
  </TabControl>
</Grid>

nun haben wir nur noch ein kleinen Schönheitsfehler, unsere Register sind nicht Sortiert, aber auch an dieser Stelle kann die CollectionViewSource helfen.

 



<Window x:Class="WpfApplication1.Window1"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="clr-namespace:WpfApplication1"    xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"    Title="Window1" Height="300" Width="300">
  <Window.Resources>
    <XmlDataProvider x:Key="data" Source="Contact.xml" XPath="contacts/ContactItem"/>
    <local:FirstLetter x:Key="firstLetter"/>
    <CollectionViewSource x:Key="cvs" Source="{StaticResource data}">
      <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="LastName" Converter="{StaticResource firstLetter}"/>
      </CollectionViewSource.GroupDescriptions>
      <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="LastName"/>
      </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
  </Window.Resources>
  <Grid>
    <TabControl DataContext="{StaticResource cvs}" ItemsSource="{Binding Path=Groups}">
      <TabControl.ItemTemplate>
        <DataTemplate>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=Name}"/>
          </StackPanel>
        </DataTemplate>
      </TabControl.ItemTemplate>
      <TabControl.ContentTemplate>
        <DataTemplate>
          <ListView ItemsSource="{Binding Items}">
            <ListView.View>
              <GridView>
                <GridViewColumn Header="Vorname" DisplayMemberBinding="{Binding XPath=FirstName}"/>
                <GridViewColumn Header="Nachame" DisplayMemberBinding="{Binding XPath=LastName}"/>
                <GridViewColumn Header="Telefon" DisplayMemberBinding="{Binding XPath=Phone}"/>
                <GridViewColumn Header="Email" DisplayMemberBinding="{Binding XPath=EmailAddress}"/>
              </GridView>
            </ListView.View>
          </ListView>
        </DataTemplate>
      </TabControl.ContentTemplate>
    </TabControl>
  </Grid>
</Window>

und abschließen natürlich auch noch ein kleiner Screenshot, und ja es sind nur die Tabs vorhanden die auch Daten enthalten

Contact.xml


Attachment: Contact.xml
Posted: Nov 03 2009, 11:06 von Lars Schmitt | mit 1 comment(s)
Abgelegt unter: ,

Kommentare

Rainer Hilmer sagte:

Colle Sache. Danke

# November 4, 2009 12:41
Kommentar abgeben

(verpflichtend) 

(verpflichtend) 

(optional)

(verpflichtend)