Benutzer mit den meisten Antworten
TreeView unter WPF mit VB.NET 2010

Frage
-
Hallo ich habe folgendes Problem:
Von einer Datenbank bekomme ich eine Tabelle mit diesem Inhalt:
Ort Name
Berlin BBSVC01
Berlin BBSVC02
Berlin BBSZC01
Braunschweig BWGHC01
Braunschweig BWGHP01
Braunschweig BWSZC01
Essen ESSZP01
Essen ESSZH01
Ich möchte diese Daten bei einer gegebenen WPF Oberfläche in eine TreeView einfügen, etwa so:
Berlin
--- BWGDC01
--- BWVFP01
--- BWWSHC01
Braunschweig
--- BGGDC01
--- BGVFP01
--- BGWSHC01
Essen
--- EMVFP01
--- EMWSHC01
Unter anderen habe ich folgendes habe ich versucht:
Dim reader As SqlDataReader = Server.TreeView("TreeView") Dim parent As New TreeViewItem Dim child As New TreeViewItem Dim buffer As String = "" 'Fill treeview trvServer.UpdateLayout() trvServer.Items.Clear() While reader.Read If buffer <> reader(0) Then buffer = reader(0) 'parent.Header = reader(0) 'trvServer.Items.Add(parent) parent.Header = trvServer.Items.Add(reader(0)) End If 'child.Header = parent.Items.Add(reader(1)) child.Header = reader(1) parent.Items.Add(child) End While reader.Close()
Leider ohne Erfolg. Es werden nur die Elternknoten (Orte) erzeugt. Die Kindknoten (Name) fehlen. Was mache ich falsch?
Antworten
-
Hallo,
ich würde dir empfehlen die Daten per LINQ in Gruppen zu sortieren:Dim groups = reader.AsParallel().Cast(Of IDataRecord).GroupBy(Function(record) record("Ort"))
Dies eGruppen können dann in einer Schleife durchlaufen werden um jeweils die oberen Elemente zu generieren. Die Unteren Elemente sind in den Gruppen jeweils enthalten und alssen sich so ebenfalls hinzufügen:For Each group In groups Dim tvi As New TreeViewItem tvi.Header = group.First()("Ort") For Each subRow In group Dim tviSub As New TreeViewItem tviSub.Header = subRow("Name") tvi.Items.Add(tviSub) Next trvServer.Items.Add(tvi) Next
Besser wäre es aber wenn du die TreeView über ihre ItemsSOurce-Eigenschaft befüllst. Hierfür musst du jedoch die Daten in eine Hierarchische Form bringen und entsprechend Templates im XAML erzeugen. EIn Beispiel in C# findest du unter Simplifying the WPF TreeView by Using the ViewModel Pattern. In meiner Signatur steht ein Konverter, falls du den C# Code nicht verstehst.Tom Lambert - C# MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Tom Lambert (Koopakiller)Moderator Freitag, 26. September 2014 20:42
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Montag, 20. Oktober 2014 14:36
-
Hi,
ergänzend zu Toms Beitrag nachfolgend ein Beispiel mit Datenbindung.XAML:
<Window x:Class="Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" Loaded="Window_Loaded" xmlns:local="clr-namespace:WpfApplication2VB"> <Window.Resources> <HierarchicalDataTemplate DataType="{x:Type local:Anzeigedaten}" ItemsSource="{Binding Path=SubItems}"> <Grid> <TextBlock Text="{Binding Text}" /> </Grid> </HierarchicalDataTemplate> </Window.Resources> <Grid> <TreeView ItemsSource="{Binding View}" /> </Grid> </Window>
Und dazu der CodeBehind
Imports System.ComponentModel Imports System.Collections.ObjectModel Imports System.Data.SqlClient Public Class Window1 Private cvs As CollectionViewSource Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Me.DataContext = Me End Sub Public ReadOnly Property View As ICollectionView Get If cvs Is Nothing OrElse cvs.View Is Nothing Then LoadData() Return cvs.View End Get End Property Private Sub LoadData() ' cvs = New CollectionViewSource Dim liste As New ObservableCollection(Of Anzeigedaten) cvs.Source = liste ' Using cn As New SqlConnection("Data Source=.;Initial Catalog=TestDB;Integrated Security=True") Using cmd As New SqlCommand("SELECT Hauptknoten, Unterknoten FROM bbredl", cn) cn.Open() Using reader As SqlDataReader = cmd.ExecuteReader While reader.Read Dim data As Anzeigedaten = (From itm In liste Where itm.Text = reader(0).ToString).FirstOrDefault If data Is Nothing Then data = New Anzeigedaten With {.Text = reader(0).ToString} liste.Add(data) End If data.SubItems.Add(New Anzeigedaten With {.Text = reader(1).ToString}) End While End Using End Using End Using End Sub End Class Public Class Anzeigedaten Public Property Text As String Public Property SubItems As New ObservableCollection(Of Anzeigedaten) End Class
--
Peter Fleischer
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Tom Lambert (Koopakiller)Moderator Freitag, 26. September 2014 20:42
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Montag, 20. Oktober 2014 14:36
Alle Antworten
-
Hallo,
ich würde dir empfehlen die Daten per LINQ in Gruppen zu sortieren:Dim groups = reader.AsParallel().Cast(Of IDataRecord).GroupBy(Function(record) record("Ort"))
Dies eGruppen können dann in einer Schleife durchlaufen werden um jeweils die oberen Elemente zu generieren. Die Unteren Elemente sind in den Gruppen jeweils enthalten und alssen sich so ebenfalls hinzufügen:For Each group In groups Dim tvi As New TreeViewItem tvi.Header = group.First()("Ort") For Each subRow In group Dim tviSub As New TreeViewItem tviSub.Header = subRow("Name") tvi.Items.Add(tviSub) Next trvServer.Items.Add(tvi) Next
Besser wäre es aber wenn du die TreeView über ihre ItemsSOurce-Eigenschaft befüllst. Hierfür musst du jedoch die Daten in eine Hierarchische Form bringen und entsprechend Templates im XAML erzeugen. EIn Beispiel in C# findest du unter Simplifying the WPF TreeView by Using the ViewModel Pattern. In meiner Signatur steht ein Konverter, falls du den C# Code nicht verstehst.Tom Lambert - C# MVP
Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets- Als Antwort vorgeschlagen Tom Lambert (Koopakiller)Moderator Freitag, 26. September 2014 20:42
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Montag, 20. Oktober 2014 14:36
-
Hi,
ergänzend zu Toms Beitrag nachfolgend ein Beispiel mit Datenbindung.XAML:
<Window x:Class="Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" Loaded="Window_Loaded" xmlns:local="clr-namespace:WpfApplication2VB"> <Window.Resources> <HierarchicalDataTemplate DataType="{x:Type local:Anzeigedaten}" ItemsSource="{Binding Path=SubItems}"> <Grid> <TextBlock Text="{Binding Text}" /> </Grid> </HierarchicalDataTemplate> </Window.Resources> <Grid> <TreeView ItemsSource="{Binding View}" /> </Grid> </Window>
Und dazu der CodeBehind
Imports System.ComponentModel Imports System.Collections.ObjectModel Imports System.Data.SqlClient Public Class Window1 Private cvs As CollectionViewSource Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Me.DataContext = Me End Sub Public ReadOnly Property View As ICollectionView Get If cvs Is Nothing OrElse cvs.View Is Nothing Then LoadData() Return cvs.View End Get End Property Private Sub LoadData() ' cvs = New CollectionViewSource Dim liste As New ObservableCollection(Of Anzeigedaten) cvs.Source = liste ' Using cn As New SqlConnection("Data Source=.;Initial Catalog=TestDB;Integrated Security=True") Using cmd As New SqlCommand("SELECT Hauptknoten, Unterknoten FROM bbredl", cn) cn.Open() Using reader As SqlDataReader = cmd.ExecuteReader While reader.Read Dim data As Anzeigedaten = (From itm In liste Where itm.Text = reader(0).ToString).FirstOrDefault If data Is Nothing Then data = New Anzeigedaten With {.Text = reader(0).ToString} liste.Add(data) End If data.SubItems.Add(New Anzeigedaten With {.Text = reader(1).ToString}) End While End Using End Using End Using End Sub End Class Public Class Anzeigedaten Public Property Text As String Public Property SubItems As New ObservableCollection(Of Anzeigedaten) End Class
--
Peter Fleischer
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Tom Lambert (Koopakiller)Moderator Freitag, 26. September 2014 20:42
- Als Antwort markiert Tom Lambert (Koopakiller)Moderator Montag, 20. Oktober 2014 14:36