Benutzer mit den meisten Antworten
ListViews in einer gruppierten ListView...

Frage
-
Hallo,
ich versuche mich jetzt seit einigen Monaten in XAML. Ich schreibe eine UWP-App in der es eine Liste von Touren gibt (mit verschiedenen Fahrern und Abfahrtzeiten). Jede einzelne Tour hat Haltestellen.
Ich habe jetzt versucht eine gruppierte ListView zu erstellen (sortiert nach Abfahrtszeiten). Funktioniert auch. Darin soll ein Header vorkommen (Fahrer, Abfahrtszeit etc.) und Footer (Rückkehr ca. blabla Uhr, Gesamt-Kilometer) und als "Item" soll die Liste der Haltestellen kommen, welche ich auch bearbeiten bzw. verschieben kann.
Also das Gruppieren klappt, ich habe es auch hinbekommen das eine Liste erstellt wird. Allerdings verhält sich die Gesamte Oberfläche sehr schlecht. Ich kann teilweise nicht die Einträge direkt anklicken, ich muss immer "neben den Text" klicken. Außerdem kommt es vor, das mehrere Einträge ausgewählt sind, in jeder ListView, ein Eintrag. Das ist natürlich alles Quatsch was ich da mache.
Wir gehe ich eine solche Sache am besten an? Ich habe eine ObservableCollection mit den Touren, und darin befinden sich die Haltestellen. Ich habe einfach nichts gefunden. Vielleicht, weil ich auch einen total falschen Ansatz habe?
Hat jemand von euch eine Idee, bitte? :-)
Liebe Grüße
Andy
Antworten
-
Hi Andy,
UWP und Net Core 5 sind unterschiedliche sich ausschließende Technologien. Da musst du dich schon entscheiden, was du wirklich willst.Hier mal eine einfache Windows Anwendung mit Core 5.
XAML:
<Window x:Class="WpfApp1.Window001" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp001" mc:Ignorable="d" Title="Window001" Height="450" Width="800"> <Window.DataContext> <local:ViewModel/> </Window.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type local:Gruppe}" ItemsSource="{Binding Fahrten}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Fahrt}" ItemsSource="{Binding Haltestellen}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Haltestelle}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> </TreeView.Resources> </TreeView> </Grid> </Window>
Und dazu die Klassen:
using System.Collections.ObjectModel; using System.Windows; namespace WpfApp001 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Gruppe> treelist; public ObservableCollection<Gruppe> View { get => treelist; } private ObservableCollection<Gruppe> LoadData() { var col = new ObservableCollection<Gruppe>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Name = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Name = $"Fahrt {k}" }; g.Fahrten.Add(f); for (int l = 1; l < 10; l++) f.Haltestellen.Add(new Haltestelle() { Name = $"Haltestelle {l}" }); } } return col; } } public class Gruppe { public string Name { get; set; } public ObservableCollection<Fahrt> Fahrten { get; set; } = new ObservableCollection<Fahrt>(); } public class Fahrt { public string Name { get; set; } public ObservableCollection<Haltestelle> Haltestellen { get; set; } = new ObservableCollection<Haltestelle>(); } public class Haltestelle { public string Name { get; set; } } }
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 5. Februar 2021 17:42
-
Hi Andy,
welche Technologie du einsetzen musst, hängt von den Zielen ab, d.h., in welcher Umgebung soll die Anwendung dann genutzt werden.Hier mal das Beispiel analog in UWP:
XAML:
<Page x:Class="App1.Page20" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App20" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Page.DataContext> <local:ViewModel/> </Page.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.ItemTemplate> <DataTemplate x:DataType="local:Data"> <TreeViewItem ItemsSource="{x:Bind SubItems}" Content="{x:Bind Name}"/> </DataTemplate> </TreeView.ItemTemplate> </TreeView> </Grid> </Page>
Und die Klassen:
using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App20 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Data> treelist; public ObservableCollection<Data> View { get => treelist; } private ObservableCollection<Data> LoadData() { var col = new ObservableCollection<Data>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Name = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Name = $"Fahrt {k}" }; g.SubItems.Add(f); for (int l = 1; l < 10; l++) f.SubItems.Add(new Haltestelle() { Name = $"Haltestelle {l}" }); } } return col; } } public class Data { public string Name { get; set; } public ObservableCollection<Data> SubItems { get; set; } = new ObservableCollection<Data>(); } public class Gruppe: Data { } public class Fahrt: Data { } public class Haltestelle: Data { } }
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 5. Februar 2021 17:43
-
Hi,
für alle, die TreeView mit TemplateSelector in einer UWP Anwendung suchen, hier eine kleine Demo:XAML:
<Page x:Class="App1.Page20" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App20" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Page.DataContext> <local:ViewModel/> </Page.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.ItemTemplateSelector> <local:MySelector> <local:MySelector.Gruppe> <DataTemplate x:DataType="local:Gruppe"> <TreeViewItem ItemsSource="{x:Bind Fahrten}"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Gruppe:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Gruppenbezeichnung}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Gruppe> <local:MySelector.Fahrt> <DataTemplate x:DataType="local:Fahrt"> <TreeViewItem ItemsSource="{x:Bind Haltestellen}"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Fahrt:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Fahrtbezeichnung}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Fahrt> <local:MySelector.Haltestelle> <DataTemplate x:DataType="local:Haltestelle"> <TreeViewItem> <StackPanel Orientation="Horizontal"> <TextBlock Text="Haltestelle:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Haltestellenname}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Haltestelle> </local:MySelector> </TreeView.ItemTemplateSelector> </TreeView> </Grid> </Page>
Und der Code dazu:
using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App20 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Data> treelist; public ObservableCollection<Data> View { get => treelist; } private ObservableCollection<Data> LoadData() { var col = new ObservableCollection<Data>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Gruppenbezeichnung = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Fahrtbezeichnung = $"Fahrt {k}" }; g.Fahrten.Add(f); for (int l = 1; l < 10; l++) f.Haltestellen.Add(new Haltestelle() { Haltestellenname = $"Haltestelle {l}" }); } } return col; } } public class Data { } public class Gruppe: Data { public string Gruppenbezeichnung { get; set; } public ObservableCollection<Data> Fahrten { get; set; } = new ObservableCollection<Data>(); } public class Fahrt: Data { public string Fahrtbezeichnung { get; set; } public ObservableCollection<Data> Haltestellen { get; set; } = new ObservableCollection<Data>(); } public class Haltestelle: Data { public string Haltestellenname { get; set; } } public class MySelector : DataTemplateSelector { protected override DataTemplate SelectTemplateCore(object item) { switch (item.GetType().Name) { case "Gruppe": return Gruppe; case "Fahrt": return Fahrt; case "Haltestelle": return Haltestelle; default: break; } return Gruppe; } public DataTemplate Gruppe { get; set; } public DataTemplate Fahrt { get; set; } public DataTemplate Haltestelle { get; set; } } }
In VB.NRT kann das so aussehen:
Namespace App20 Public Class ViewModel Public Sub New() treelist = LoadData() End Sub Private treelist As ObservableCollection(Of Data) Public ReadOnly Property View As ObservableCollection(Of Data) Get Return treelist End Get End Property Private Function LoadData() As ObservableCollection(Of Data) Dim col As New ObservableCollection(Of Data) For i = 1 To 9 Dim g = New Gruppe() With {.Gruppenbezeichnung = $"Gruppe {i}"} col.Add(g) For k = 1 To 9 Dim f = New Fahrt() With {.Fahrtbezeichnung = $"Fahrt {k}"} g.Fahrten.Add(f) For l = 1 To 10 f.Haltestellen.Add(New Haltestelle() With {.Haltestellenname = $"Haltestelle {l}"}) Next Next Next Return col End Function End Class Public Class Data End Class Public Class Gruppe Inherits Data Public Property Gruppenbezeichnung As String Public Property Fahrten As New ObservableCollection(Of Data) End Class Public Class Fahrt Inherits Data Public Property Fahrtbezeichnung As String Public Property Haltestellen As New ObservableCollection(Of Data) End Class Public Class Haltestelle Inherits Data Public Property Haltestellenname As String End Class Public Class MySelector Inherits DataTemplateSelector Protected Overrides Function SelectTemplateCore(item As Object) As DataTemplate Select Case item.GetType().Name Case "Gruppe" : Return Gruppe Case "Fahrt" : Return Fahrt Case "Haltestelle" : Return Haltestelle Case Else Return Nothing End Select End Function Public Property Gruppe As DataTemplate Public Property Fahrt As DataTemplate Public Property Haltestelle As DataTemplate End Class End Namespace
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks
- Bearbeitet Peter Fleischer Sonntag, 7. Februar 2021 11:39
- Als Antwort markiert AndreasMahub Montag, 8. Februar 2021 08:23
Alle Antworten
-
Hi Andy,
warum muss es ein ListView sein? Hast du mal über einen TreeView mit entsprechenden Templates gedacht?--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks -
Hi Andy,
warum muss es ein ListView sein? Hast du mal über einen TreeView mit entsprechenden Templates gedacht?
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, TricksGuten Morgen,
ganz ehrlich? Nein, habe ich nicht daran gedacht. Alleine schon wegen der Optik habe ich nicht an eine TreeView gedacht, weil, da bin ich wohl noch etwas "Altbacken" was das Thema angeht. Ich probiere das gleich mal aus bzw. werde mich darin mal belesen was man da machen kann :-)
Gruß
Andy -
Hi Andy,
nach deiner Beschreibung sehe ich da 3 Knotenebenen, die aufgeklappt werden können:1. Gruppe
2. Fahrer, Rückkehr
3. in 2. eingebettet aufklappbar Haltestellen
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks -
Hi Andy,
nach deiner Beschreibung sehe ich da 3 Knotenebenen, die aufgeklappt werden können:1. Gruppe
2. Fahrer, Rückkehr
3. in 2. eingebettet aufklappbar Haltestellen
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, TricksHallo Peter,
ja, klar, wie gesagt, ich habe da überhaupt nicht an das TreeView-Control gedacht. Ich probiere mich gerade an dem TreeView-Control, aber scheitere schon an einer Kleinigkeit "Fehler beim Abrufen des untergeordneten Elements am Index 0".
<Grid> <TreeView x:Name="TreeViewCtl"> <TreeView.RootNodes> <TreeViewNode Content="aaa" IsExpanded="True"> <TreeViewNode.Children> <TreeViewNode Content="Zeile1"/> <TreeViewNode Content="Zeile2"/> <TreeViewNode Content="Zeile3"/> </TreeViewNode.Children> </TreeViewNode> </TreeView.RootNodes> </TreeView> </Grid>
Gruß
Andy
-
Hi,
Oh, nach dem kompilieren ging es und mir wurde im Designer was angezeigt. Manchmal nervt mich da Visual Studio. Ich habe sehr oft Fehler die mir angezeigt werden, und ich suche dann wie blöd, um am Ende festzustellen ein Bereinigen der Projektmappe hilft dann.
Jetzt z.B. sehe ich links in der Toolbox gar nichts von einem TreeView-Control, im XAML-Editor wiederum schon. Ich benutze eh nicht den Designer, sondern schreibe den XAML-Code komplett selbst, weil ich irgendwo in einem Englischsprachigen Forum gelesen habe, man sollte sich lieber gleich angewöhnen den XAML-Code selbst zu schreiben, dann lernt man auch besser, was wie wo wann passiert, statt es sich "bauen zu lassen".
Das wird bei mir denke ich noch seeeehr lange dauern bis ich das alles begriffen habe. Abe ich muss unbedingt weg von dem veralteten Windows-Standard-Controls.
Gruß
Andy -
Mahlzeit,
sagt mal, wenn Beispiele aus dem Internet zu den einfachsten Sachen einfach nicht funktionieren wollen (wie z.B. dieses hier), liegt das dann wirklich nur an mir? Oder gibt es wirklich diesen <TreeViewItem>?
Seit Monaten versuche ich mich in XAML. Seit Monaten sehe ich mich mit Beispiel konfrontiert, die einfach nicht funktionieren wollen. Ich verliere so langsam aber sicher wirklich die Lust an UWP und XAML und bin kurz davor frustriert den Rechner aus dem Fenster zu werfen.
Ich habe es in den letzten 4 Stunden nicht einmal geschafft eine simple TreeView darzustellen :-(
Gruß
Andy -
Hi Andy,
du musst erst einmal unterscheiden, welchen Projekttyp du hats, welche Framework Version du einsetzt und dann schauen, ob das Beispiel auch für diese Umgebung gilt. Wenn du von UWP schreibst, dann entscheidest du dich für NET Core und da musst du weiter für Windows Anwendungen sehen, welche minimale und welche Zielversion von Windows du nutzt. Bis einschließlich Creators Update wird standardmäßig kein TreeView unterstützt. Da benötigst du vielleicht ein NuGet Package.Ich empfehle dir, entweder mit einem WPF Projekt zu beginnen und das Framework 4.8 zu nutzen. Da funktionieren die meisten Beispiele, z.B. auch das aus deinem Link. Wenn es eine UWP Anwendung sein soll, dann setzte für Windows mindestens bei Build 1803 auf. Da sind aber nicht alle Klassen verfügbar, die es im Framework 4 gibt. Trotzdem kannst du aber eine vernünftige Anwendung erstellen.
Ich kann die ein TreeView Beispiel zeigen, wenn du kurz Programmiersprache und Datenmodell mitteilst.
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks -
Hi Andy,
du musst erst einmal unterscheiden, welchen Projekttyp du hats, welche Framework Version du einsetzt und dann schauen, ob das Beispiel auch für diese Umgebung gilt. Wenn du von UWP schreibst, dann entscheidest du dich für NET Core und da musst du weiter für Windows Anwendungen sehen, welche minimale und welche Zielversion von Windows du nutzt. Bis einschließlich Creators Update wird standardmäßig kein TreeView unterstützt. Da benötigst du vielleicht ein NuGet Package.Ich empfehle dir, entweder mit einem WPF Projekt zu beginnen und das Framework 4.8 zu nutzen. Da funktionieren die meisten Beispiele, z.B. auch das aus deinem Link. Wenn es eine UWP Anwendung sein soll, dann setzte für Windows mindestens bei Build 1803 auf. Da sind aber nicht alle Klassen verfügbar, die es im Framework 4 gibt. Trotzdem kannst du aber eine vernünftige Anwendung erstellen.
Ich kann die ein TreeView Beispiel zeigen, wenn du kurz Programmiersprache und Datenmodell mitteilst.
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, TricksHi Peter,
also, eigentlich möchte ich ja komplett Umsteigen, also weg vom Framework, weil, .NET Core ist ja die neue Zukunft und die Framework wird (bis auf Sicherheitsupdates) nicht mehr weiter entwickelt. Auch habe ich es Jahrelang vor mir hergeschoben von VB.NET wegzukommen und endlich auf C# komplett umzusteigen. Damit habe ich letztes Jahr begonnen und eigentlich schreibe ich nur noch in C#.
Aber bei der Oberfläche (also der UI) ernte ich bisher nur Frust statt Lust. Auf der einen Seite sehe ich ja wie unglaublich "Grenzenlos" man teilweise da gestalten kann und es flüssig läuft. Auf der anderen Seite bin ich vielleicht auch zu Alt einfach um das noch zu verstehen.
Auch habe ich versucht mal Bücher zu finden zu dem "neuen" Thema aber auch nicht wirklich fündig geworden. Die Themen werden eher in einzelnen Kapiteln kurz angerissen, weil, es ist zu umfangreich, also, denke ich, um alles aufzuführen damit jeder seinen Nutzen daraus findet.
Ja, Peter, sehr gerne, zeig mir mal bitte kurz ein simples Beispiel mit einem TreeView unter UWP .NET Core 5 in C#. Bitte mach dir jetzt keine große Arbeit, mir reicht ein simples Beispiel wo ich einen TreeView habe, wo ich die Einträge aufklappen kann und daran befinden sich z.B. ein paar TextBlock's in die ich meine Daten reinwerfen kann.
Mir raucht gerade leider wirklich der Kopf. Auf der einen Seite möchte ich den Rechner frustriert runterfahren und Schluss für heute. Auf der anderen Seite möchte ich es verstehen und wegrennen bringt nichts :-)
Gruß
Andy -
Hi Andy,
UWP und Net Core 5 sind unterschiedliche sich ausschließende Technologien. Da musst du dich schon entscheiden, was du wirklich willst.Hier mal eine einfache Windows Anwendung mit Core 5.
XAML:
<Window x:Class="WpfApp1.Window001" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp001" mc:Ignorable="d" Title="Window001" Height="450" Width="800"> <Window.DataContext> <local:ViewModel/> </Window.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type local:Gruppe}" ItemsSource="{Binding Fahrten}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Fahrt}" ItemsSource="{Binding Haltestellen}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type local:Haltestelle}"> <Label Content="{Binding Name}"/> </HierarchicalDataTemplate> </TreeView.Resources> </TreeView> </Grid> </Window>
Und dazu die Klassen:
using System.Collections.ObjectModel; using System.Windows; namespace WpfApp001 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Gruppe> treelist; public ObservableCollection<Gruppe> View { get => treelist; } private ObservableCollection<Gruppe> LoadData() { var col = new ObservableCollection<Gruppe>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Name = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Name = $"Fahrt {k}" }; g.Fahrten.Add(f); for (int l = 1; l < 10; l++) f.Haltestellen.Add(new Haltestelle() { Name = $"Haltestelle {l}" }); } } return col; } } public class Gruppe { public string Name { get; set; } public ObservableCollection<Fahrt> Fahrten { get; set; } = new ObservableCollection<Fahrt>(); } public class Fahrt { public string Name { get; set; } public ObservableCollection<Haltestelle> Haltestellen { get; set; } = new ObservableCollection<Haltestelle>(); } public class Haltestelle { public string Name { get; set; } } }
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 5. Februar 2021 17:42
-
Hi Andy,
UWP und Net Core 5 sind unterschiedliche sich ausschließende Technologien. Da musst du dich schon entscheiden, was du wirklich willst....
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, TricksHallo Peter,
mein Gott, bin ich auf dem Holzweg die ganzen Monate gewesen. Ich blicke auch ehrlich gesagt irgendwann nicht mehr durch. Framework, Standard, .NET, UWP, WPF... Langsam geht mir ein Licht auf. Dein Beispiel hat natürlich sofort funktioniert, den XAML-Tag <HierarchicalDataTemplate...> hab ich z.B. in UWP nie gefunden. Ich bin irgendwann echt verzweifelt, weil, ja, ich blicke teilweise echt nicht mehr durch welcher Versionen, Frameworks etc. es gibt, wofür sie sind, wann man sie in welchem Szenario einsetzen sollte.
Danke Peter, dass du mir jetzt kurzfristig mir mal Licht ins Dunkle gebracht hast.
Gruß
Andy -
Hi Andy,
welche Technologie du einsetzen musst, hängt von den Zielen ab, d.h., in welcher Umgebung soll die Anwendung dann genutzt werden.Hier mal das Beispiel analog in UWP:
XAML:
<Page x:Class="App1.Page20" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App20" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Page.DataContext> <local:ViewModel/> </Page.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.ItemTemplate> <DataTemplate x:DataType="local:Data"> <TreeViewItem ItemsSource="{x:Bind SubItems}" Content="{x:Bind Name}"/> </DataTemplate> </TreeView.ItemTemplate> </TreeView> </Grid> </Page>
Und die Klassen:
using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App20 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Data> treelist; public ObservableCollection<Data> View { get => treelist; } private ObservableCollection<Data> LoadData() { var col = new ObservableCollection<Data>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Name = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Name = $"Fahrt {k}" }; g.SubItems.Add(f); for (int l = 1; l < 10; l++) f.SubItems.Add(new Haltestelle() { Name = $"Haltestelle {l}" }); } } return col; } } public class Data { public string Name { get; set; } public ObservableCollection<Data> SubItems { get; set; } = new ObservableCollection<Data>(); } public class Gruppe: Data { } public class Fahrt: Data { } public class Haltestelle: Data { } }
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 5. Februar 2021 17:43
-
Hallo Peter,
daaaanke, werde ich morgen parallel dazu mal auch ausprobieren. Auch hier erkenne ich schon was ich vorher nicht gesehen habe.
Aber heute nicht mehr, ich bin heute Vormittag wirklich schon komplett verzweifelt. Die ganzen Monate war ich komplett auf dem Holzweg. Es hat zwar irgendwie funktioniert, trotzdem war 1+2 = 3 und nicht 2. Also, weder Fisch noch Fleisch.
Irgendwie habe ich das Gefühl, ich habe Monatelang auf ein Bild gestarrt und sehe erst jetzt das da eigentlich 2 Gesichter sind :-D Ich bin fix und alle und mache Feierabend für heute.
Peter! Danke nochmal! :-)
Gruß
Andy -
Hallo Peter,
so, nachdem ich mich jetzt mehrere Stunden mit dem Thema beschäftigt habe, habe ich mich dazu entschlossen bei UWP zu bleiben. Mir fehlen bei .NET Core WPF einfach ein paar Sachen die in UWP (wie ich finde) angenehmer sind.
Einzig das TreeView-Control als solches fand ich erst etwas enttäuschend. Erst als ich noch etwas rumgesucht habe habe ich mich mit dem ItemTemplateSelector beschäftigt. Und, funktioniert auch auf UWP :-) Die erste Ebene zeigt immer den Header an, die zweite Ebene eine ListView mit allen Haltestellen :-)
Vielen Dank nochmal :-)
Gruß
Andy -
Hi,
für alle, die TreeView mit TemplateSelector in einer UWP Anwendung suchen, hier eine kleine Demo:XAML:
<Page x:Class="App1.Page20" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App20" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Page.DataContext> <local:ViewModel/> </Page.DataContext> <Grid> <TreeView ItemsSource="{Binding View}" Margin="5"> <TreeView.ItemTemplateSelector> <local:MySelector> <local:MySelector.Gruppe> <DataTemplate x:DataType="local:Gruppe"> <TreeViewItem ItemsSource="{x:Bind Fahrten}"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Gruppe:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Gruppenbezeichnung}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Gruppe> <local:MySelector.Fahrt> <DataTemplate x:DataType="local:Fahrt"> <TreeViewItem ItemsSource="{x:Bind Haltestellen}"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Fahrt:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Fahrtbezeichnung}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Fahrt> <local:MySelector.Haltestelle> <DataTemplate x:DataType="local:Haltestelle"> <TreeViewItem> <StackPanel Orientation="Horizontal"> <TextBlock Text="Haltestelle:" Margin="0 0 5 0"/> <TextBlock Text="{Binding Haltestellenname}"/> </StackPanel> </TreeViewItem> </DataTemplate> </local:MySelector.Haltestelle> </local:MySelector> </TreeView.ItemTemplateSelector> </TreeView> </Grid> </Page>
Und der Code dazu:
using System.Collections.ObjectModel; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace App20 { public class ViewModel { public ViewModel() => treelist = LoadData(); public ObservableCollection<Data> treelist; public ObservableCollection<Data> View { get => treelist; } private ObservableCollection<Data> LoadData() { var col = new ObservableCollection<Data>(); for (int i = 1; i < 10; i++) { var g = new Gruppe() { Gruppenbezeichnung = $"Gruppe {i}" }; col.Add(g); for (int k = 1; k < 10; k++) { var f = new Fahrt() { Fahrtbezeichnung = $"Fahrt {k}" }; g.Fahrten.Add(f); for (int l = 1; l < 10; l++) f.Haltestellen.Add(new Haltestelle() { Haltestellenname = $"Haltestelle {l}" }); } } return col; } } public class Data { } public class Gruppe: Data { public string Gruppenbezeichnung { get; set; } public ObservableCollection<Data> Fahrten { get; set; } = new ObservableCollection<Data>(); } public class Fahrt: Data { public string Fahrtbezeichnung { get; set; } public ObservableCollection<Data> Haltestellen { get; set; } = new ObservableCollection<Data>(); } public class Haltestelle: Data { public string Haltestellenname { get; set; } } public class MySelector : DataTemplateSelector { protected override DataTemplate SelectTemplateCore(object item) { switch (item.GetType().Name) { case "Gruppe": return Gruppe; case "Fahrt": return Fahrt; case "Haltestelle": return Haltestelle; default: break; } return Gruppe; } public DataTemplate Gruppe { get; set; } public DataTemplate Fahrt { get; set; } public DataTemplate Haltestelle { get; set; } } }
In VB.NRT kann das so aussehen:
Namespace App20 Public Class ViewModel Public Sub New() treelist = LoadData() End Sub Private treelist As ObservableCollection(Of Data) Public ReadOnly Property View As ObservableCollection(Of Data) Get Return treelist End Get End Property Private Function LoadData() As ObservableCollection(Of Data) Dim col As New ObservableCollection(Of Data) For i = 1 To 9 Dim g = New Gruppe() With {.Gruppenbezeichnung = $"Gruppe {i}"} col.Add(g) For k = 1 To 9 Dim f = New Fahrt() With {.Fahrtbezeichnung = $"Fahrt {k}"} g.Fahrten.Add(f) For l = 1 To 10 f.Haltestellen.Add(New Haltestelle() With {.Haltestellenname = $"Haltestelle {l}"}) Next Next Next Return col End Function End Class Public Class Data End Class Public Class Gruppe Inherits Data Public Property Gruppenbezeichnung As String Public Property Fahrten As New ObservableCollection(Of Data) End Class Public Class Fahrt Inherits Data Public Property Fahrtbezeichnung As String Public Property Haltestellen As New ObservableCollection(Of Data) End Class Public Class Haltestelle Inherits Data Public Property Haltestellenname As String End Class Public Class MySelector Inherits DataTemplateSelector Protected Overrides Function SelectTemplateCore(item As Object) As DataTemplate Select Case item.GetType().Name Case "Gruppe" : Return Gruppe Case "Fahrt" : Return Fahrt Case "Haltestelle" : Return Haltestelle Case Else Return Nothing End Select End Function Public Property Gruppe As DataTemplate Public Property Fahrt As DataTemplate Public Property Haltestelle As DataTemplate End Class End Namespace
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks
- Bearbeitet Peter Fleischer Sonntag, 7. Februar 2021 11:39
- Als Antwort markiert AndreasMahub Montag, 8. Februar 2021 08:23