Zu beachten: Ist vlt. bisserl ungeschickt, dassichhier mit einer ganz allgemeinen Grundlage datenbänkerischen Denkens einsteige, und mich auch darauf konzentriere. Dabei mussich ganz viele Eigenheiten und Prinzipien von Wpf vorraussetzen, auf die ich im WpfTreeview-Tut eingehe:
Wpf: MVVM-Pattern, DataContext und DataTemplates im Treeview.
Dabei ist die Wpf-Treeview ein viel anspruchsvolleres Control als die List- und Text-Boxen, mit denen man die 4 Views zusammenbasteln kann.
Vlt. mache ich auch mal ein 4-Views Tut für WindowsForms, denn es handelt sich um allgemeine Architektur- und Präsentations-Prinzipien der Informatik - überhaupt nicht auf Wpf oder WinForms beschränkt - auch nicht auf Vb.Net, oder die .Net-Sprachen überhaupt.
Ein wesentliches Konzept der Datenbänkerei ist, was ich "die vier Views" nenne: vier verschiedene Konzepte, wie sich komplexe Daten präsentieren lassen.
Alle diese Views präsentieren die Daten - damit meine ich: prinzipiell ermöglichen sie volle Bearbeitung (Löschen, Zufügen, editieren von Datensätzen) - was natürlich je nach Erforderlichkeit vom Programm her eingeschränkt wird.
Die Views sind auch beliebig kombinierbar - man kann auch 3-stufige Parent-Child-Views bauen, oder Detail-Präsentation mit den anderen Views kombinieren - wies eben erforderlich und sinnvoll ist.
Ich beginne das Tut mit einem super-einfachen Detail-View - nur Lese-Funktionalität: Nämlich eine Liste von FileInfos wird angezeigt (weil ich das einfach generieren kann).
Vom FileInfo werden 3 Properties angezeigt: Name, Fullname und Length (Attribute, IsReadOnly, LastAccessTime und Zeugs lassich einfach weg)
Das ViewModel:
Es gibt nur eine Property, Files - nämlich die Liste mit den FileInfos. Zum MVVM-Pattern, und wie und warum man so ein Model ans Xaml bindet, mögeman sich im grundlegenderen Tut schlau machen: WpfTreeview-Tut
Das Xaml:
Zunächstmal ganz wesentlich für jedes Xaml, wie der DataContext definiert ist, denn dieser pflanzt sich durch alle eingeschachtelten Controls fort. Hier ist DataContext="{x:Static my:MainModel.Root}" gebunden, also ans MainModel.
Im Grid links (Grid.Column="0") ist nun die Listbox plaziert, mit ItemsSource gebunden an MainModel.Files.
Rechts (Grid.Column="1") eine Border (also ein Rahmen) - mit DataContext gebunden an dieselbe Property!
In der Border ein Grid mit ungebundenen Textblöcken zur Beschriftung, und gebundenen Textblöcken zur Anzeige der einzelnen Properties eines FileInfos.
Die Synchronisation, also dass der Inhalt der Border nun genau das FileInfo präsentiert, welches in der Listbox angewählt ist - das wird erzwungen durch: Listbox.IsSynchronizedWithCurrentItem="True".
Jo, lustig, ne? Mehr zur Erläuterung speziell des DetailViews ist nicht erforderlich - alles andere wurde im WpfTreeview-Tut besprochen.
Wpf: MVVM-Pattern, DataContext und DataTemplates im Treeview.
Dabei ist die Wpf-Treeview ein viel anspruchsvolleres Control als die List- und Text-Boxen, mit denen man die 4 Views zusammenbasteln kann.
Vlt. mache ich auch mal ein 4-Views Tut für WindowsForms, denn es handelt sich um allgemeine Architektur- und Präsentations-Prinzipien der Informatik - überhaupt nicht auf Wpf oder WinForms beschränkt - auch nicht auf Vb.Net, oder die .Net-Sprachen überhaupt.
Ein wesentliches Konzept der Datenbänkerei ist, was ich "die vier Views" nenne: vier verschiedene Konzepte, wie sich komplexe Daten präsentieren lassen.
- Detail-View: Gegeben ist eine Liste von DatenObjekten, deren jedes mehrere Properties hat. In einem ListenControl präsentiert man diese Datenobjekte nun bewusst unvollständig, häufig zeigt man nur eine einzige (signifikante) Property an - etwa den Namen.
In der Liste wählt man nun ein Objekt aus, und in beigeordneten EinzelControls werden alle weiteren Properties des aktuell angewählten Objekts präsentiert.
Ein DetailView ist angesagt, wenn Datenobjekte viele Properties beinhalten, oder wenn einzelne Properties (etwa Bilder, oder langer Text) zuviel Platz beanspruchen würden, um in eine Tabellen-Zeile zu passen.
- Parent-Child-View: Gegeben sind DatenObjekte, deren jedes weitere DatenObjekte enthalten. Links werden zB. die übergeordneten Objekte angezeigt, und rechts eine Liste oder Tabelle der untergeordneten Objekte.
Ein Beispiel, was jeder kennt - der DateiBrowser: links wählt man einen Ordner, und rechts finden sich alle Dateien, die in diesem Ordner drin sind.
- Joining-View: In einer großen Tabelle werden alle untergeordneten DatenObjekte angezeigt, aber bestimmte Spalten bestehen aus ComboBoxen, die Werte aus übergeordneten Tabellen anzeigen.
Beispielsweise können alle Artikel angezeigt sein, und in einer Combobox-Spalte wird jeweils die Kategorie angezeigt, der ein Artikel angehört. Der JoiningView sieht prinzipiell aus wie das Ergebnis einer Inner-Join - Abfrage in Sql, jedoch, da die Tabellen getrennt geladen wurden, ist es möglich, über die Comboboxen einen Artikel einer anderen Kategorie zuzuordnen.
- m:n-View: vom Prinzip her eine Kombination aus Parent-Child und Joining-View. Angenommen die Daten von Kunden, Kundenbetreuern und Bestellungen.
Im Parent-Child-View kann ein Kunde aus einer Liste gewählt werden, und auf der Child-Seite sieht man seine Bestellungen. Aber (Joining-View) eine Combobox-Spalte der Bestellung zeigt den KundenBetreuer an, der diese Bestellung entgegengenommen hat.
Alle diese Views präsentieren die Daten - damit meine ich: prinzipiell ermöglichen sie volle Bearbeitung (Löschen, Zufügen, editieren von Datensätzen) - was natürlich je nach Erforderlichkeit vom Programm her eingeschränkt wird.
Die Views sind auch beliebig kombinierbar - man kann auch 3-stufige Parent-Child-Views bauen, oder Detail-Präsentation mit den anderen Views kombinieren - wies eben erforderlich und sinnvoll ist.
Ich beginne das Tut mit einem super-einfachen Detail-View - nur Lese-Funktionalität: Nämlich eine Liste von FileInfos wird angezeigt (weil ich das einfach generieren kann).
Vom FileInfo werden 3 Properties angezeigt: Name, Fullname und Length (Attribute, IsReadOnly, LastAccessTime und Zeugs lassich einfach weg)
Das ViewModel:
VB.NET-Quellcode
- Imports System.Collections.ObjectModel
- Imports System.IO
- Public Class MainModel
- Public Shared ReadOnly Root As New MainModel
- Private Sub New()
- If GalaSoft.MvvmLight.ViewModelBase.IsInDesignModeStatic Then Return
- Dim di = New DirectoryInfo("..\..")
- Files = New ObservableCollection(Of FileInfo)(di.GetFiles("*.*", SearchOption.AllDirectories))
- End Sub
- Public Property Files As ObservableCollection(Of FileInfo)
- End Class
Das Xaml:
XML-Quellcode
- <Window x:Class="MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:io="clr-namespace:System.IO;assembly=mscorlib"
- Title="MainWindow" Height="350" Width="525"
- xmlns:my="clr-namespace:DetailView"
- DataContext="{x:Static my:MainModel.Root}" WindowState="Maximized">
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" MinWidth="20" />
- <ColumnDefinition />
- </Grid.ColumnDefinitions>
- <ListBox Grid.Column="0" MinWidth="60"
- ItemsSource="{Binding Path=Files}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>
- <Border Grid.Column="1" Height="100" Margin="10" BorderBrush="Aqua" BorderThickness="1" Padding="8" DataContext="{Binding Path=Files}">
- <Grid >
- <Grid.RowDefinitions>
- <RowDefinition />
- <RowDefinition />
- <RowDefinition />
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition/>
- </Grid.ColumnDefinitions>
- <TextBlock Grid.Row="0" Text="Name:" Margin="0,0,5,0" />
- <TextBlock Grid.Row="1" Text="FullName:" Margin="0,0,5,0" />
- <TextBlock Grid.Row="2" Text="Length:" Margin="0,0,5,0" />
- <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Name}"/>
- <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=FullName}"/>
- <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Length}"/>
- </Grid>
- </Border>
- </Grid>
- </Window>
Im Grid links (Grid.Column="0") ist nun die Listbox plaziert, mit ItemsSource gebunden an MainModel.Files.
Rechts (Grid.Column="1") eine Border (also ein Rahmen) - mit DataContext gebunden an dieselbe Property!
In der Border ein Grid mit ungebundenen Textblöcken zur Beschriftung, und gebundenen Textblöcken zur Anzeige der einzelnen Properties eines FileInfos.
Die Synchronisation, also dass der Inhalt der Border nun genau das FileInfo präsentiert, welches in der Listbox angewählt ist - das wird erzwungen durch: Listbox.IsSynchronizedWithCurrentItem="True".
Jo, lustig, ne? Mehr zur Erläuterung speziell des DetailViews ist nicht erforderlich - alles andere wurde im WpfTreeview-Tut besprochen.
Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von „ErfinderDesRades“ ()