TabControl mit dynamischen Tabs und ListView im tab

  • WPF

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von seh.

    TabControl mit dynamischen Tabs und ListView im tab

    Hallo,

    besonders an @Nofear23m weil WPF Gott :thumbsup:
    Vielleicht kann mir jemand helfen weil ich mir eine Aufgabe vorgenommen habe, die leider weiß Gott meine WPF Kenntnisse übersteigen.

    Ich will einen Shop Editor für ein Game basteln der sehr einfach ist. Jeder Shop ist gleichzeitig ein NPC mit einem Namen, in einer ComboBox habe ich schon ein Binding auf meine NPC Liste gemacht und das funktioniert auch prima.

    Jetzt kann jeder Shop / NPC bis zu 4 Tabs haben. An sich ist es im Spiel nichts anderes als ein TabControl mit aber max. 4 Tabs. Meistens sind das dann Kategorietabs wie z.B. Tab 1 = Lebenstränke, Tab 2 = Manatränke, Tab 3 = Sonstige Tränke, Tab 4 = Premium Tränke. Prinzip damit denke ich klar.

    Jeder Tab kann dann theoretisch unendlich Items beinhalten. Ein Tab hat also eine Liste von Items.
    Nun zum Shop Editor. Wie schon erwähnt, ich wähle den zu bearbeitenden Shop in der ComboBox aus und in meinem ViewModel habe ich schon eine Liste mit allen schon existierenden ShopDaten.
    Prinzipiell ist das eine List<NPC>, die NPC-Klasse hat ein Shop -Member of Type Shop, darin ist eine List<ShopTab> und ShopTab hat eine List of Items.

    Mein Datentemplate hatte ich jetzt für mein komplettes TabControl mir so vorgestellt:

    XML-Quellcode

    1. ​<TabControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding TabItems}">
    2. <TabControl.ContentTemplate>
    3. <DataTemplate>
    4. <ListView HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    5. <ListView.ItemTemplate>
    6. <DataTemplate>
    7. <StackPanel Orientation="Horizontal">
    8. <Image Width="25" Height="25" />
    9. <TextBlock Text="{Binding ItemId}" VerticalAlignment="Center" />
    10. </StackPanel>
    11. </DataTemplate>
    12. </ListView.ItemTemplate>
    13. </ListView>
    14. </DataTemplate>
    15. </TabControl.ContentTemplate>
    16. </TabControl>


    Ich habe gelesen, dass das ContentTemplate des TabControls für den Content auf der TabPage ist und das ItemTemplate ist für den Headerbereich jedes TabItems, da mir der Headerbereich egal ist und einfach den Namen des Shop Tabs bekommt benötige ich dort glaub ich keine Anpassung oder?
    Jedenfalls war die Überlegung beim ContentTemplate halt ein ListView darin, und das ItemTemplate der ListView ein StackPanel Horizontal ausgerichtet welches dann ein Bildchen vom Item und den Item Namen (erstmal nur Item Id) enthält.

    Problem ist jetzt wie ich das ganze zur Laufzeit befülle, da hab ich keine Ahnung wie das gehen soll und für Tipps oder Korrekturen in meinem XAML bin ich natürlich offen, vielleicht funktioniert es ja auch nicht so wie ich mir das vorstelle?

    Danke im Voraus

    Mfg
    Hallo

    Habs durchgelesen und verstehe leider nix. Sorry, ich blick nicht durch. Beschränke dich bei der erklärung bitte mal auf das wesentliche oder lade eine Demo hoch mit einer erklärung was nicht hinhaut.
    Wie ich das sehe geht es ja "nur" darum in dem ListView (des DataTemplates) Items anzuzeigen. Dann musst du ja nur das ItemsSource Property Binden und gut? Oder verstehe ich das falsch?
    Im obigem code sehe ich nicht das du das ListView->ItemsSource gebunden hast.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    @Nofear23m Danke für die schnelle Antwort und sorry für die anscheinend miserable Erklärung. Ich versuche es nochmal:

    Im ViewModel habe ich eine ObservableCollection<Npc>. Die Npc Klasse hat einen Member "Shop" vom TypNpcShop. Die NpcShop Klasse hat einen Member vom Typ ObservableCollection<ShopItem>[] (Ich betone hier ein Array von einer Collection). Warum ein Array? Jeder Eintrag im Array = 1 Shop Tab im Shop.
    Da ich oben erwähnt hatte max. 4 Shop Tabs ist das Array also nie größer als 4. Es ist aber dennoch variabel da nicht jeder Npc 4 Shop Tabs hat.
    Die Klasse ShopItem hat jetzt die ItemId des Items und die ist was ich jetzt erstmal anzeigen lassen will, lassen wir das Bildchen außen vor.

    Ich will jetzt mein TabControl in meinem ShopEditor an die ObservableCollection<ShopItem>[] von dem ausgewählten Npc welcher sich in der ObservableCollection<Npc> befindet binden und jedes ListView an die ObservableCollection<ShopItem> des jeweiligen Tabs binden und der TextBlock soll dann den Text des String-Members "ItemId" in der ShopItem Klasse haben.

    Ob das so jetzt verständlicher war weiß ich nicht :D

    Das TabControl zu binden schaffe ich noch, aber weiter weiß ich nicht.

    Edit: Angenommen das TabControl ist jetzt gebunden, der Shop hat vier Tabs. Im DataTemplate muss ich das ListView ja auch binden, nur woher weiß XAML jetzt, in welchem Tab sich das ListView befindet .. ergo aus welchem Eintrag im Tab Array soll er sich die Items ziehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „seh“ ()

    Hallo

    OK. Laut deiner Beschreibung sollte folgendes passen.

    XML-Quellcode

    1. <TabControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding TabItems}">
    2. <TabControl.ContentTemplate>
    3. <DataTemplate>
    4. <ListView ItemsSource="{Binding ShopItem}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    5. <ListView.ItemTemplate>
    6. <DataTemplate>
    7. <StackPanel Orientation="Horizontal">
    8. <Image Width="25" Height="25" />
    9. <TextBlock Text="{Binding ItemId}" VerticalAlignment="Center" />
    10. </StackPanel>
    11. </DataTemplate>
    12. </ListView.ItemTemplate>
    13. </ListView>
    14. </DataTemplate>
    15. </TabControl.ContentTemplate>
    16. </TabControl>


    Aber ich denke für solche eine verschachtelung gibt es nicht wirklich eine gute erklärung. Ich bin auch recht schlecht darin sollche Dinge nachzuvollziehen.
    Am besten ist es glaube ich wenn du wirklch ein Beispiel erstellst. Geht ja recht schnell, nur mit dem wichtigsten.

    Oder lade mal ein Diagram hoch. Da kann man sich meisst auch was darunter vorstellen. Ein Bild sagt mehr als 1000 Worte!!!!

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hi @Nofear23m

    Ich habe es gerade durch Zufall selbst gelöst, und zwar funktioniert es wie du oben gemacht hast, nur dass das Binding der ListView leer war. Also so:

    XML-Quellcode

    1. <ListView ItemsSource="{Binding}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    Sodass die ListView an den DataContext gebunden wird.

    So funktioniert es jetzt genau wie ich will, war ja tatsächlich einfacher als gedacht.
    Hallo

    Super!

    Wenn es wie in deinem Fall ein etwas komplizierteres Modell ist empfehle ich ein Bild von einem Diaram hochzuladen. Dann kann sich jeder besser vorstellen wie dein ViewModel aufgebaut ist.

    Schöne Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Da stimme ich dir voll und ganz zu. In Zukunft werde ich das Ganze versuchen wesentlich besser darzustellen durch Bilder, Diagramme, Codebeispiele.
    Das Projekt befindet sich hier github.com/Yothri/Rhisis/tree/…c/tools/Rhisis.ShopEditor

    Hierfür relevant im Ordner ViewModels das MainViewModel und im Views Order das MainWindow (mehr gibts ja aktuell auch nicht).
    Wenn dann das Programm ausgeführt wird, werden die vorhandenen Npcs und deren Shop Inhalte eingelesen aus Dateien und dann kann man in der ComboBox den NPC auswählen und jetzt erstmal die vorhandenen Item Ids die er anbietet begutachten.



    Die Daten werden in Dateien im JSON Format abgelegt/gelesen. Dieser NPC hat 4 Tabs und dort sieht man die jeweiligen Item Ids pro Tab die er anbietet. Die anderen Tabs sind mit genau den Item befüllt wie sie sich auch im Spiel befinden. Perfekt!

    Danke für die Hilfe :)

    Edit: Achso vielleicht noch eine andere Sache, da die Shop Dateien nur die Item Ids, nicht aber die Item Bezeichnung beinhalten muss ich jetzt Item Id und Item Bezeichnung assoziieren. Dafür nehmen wir jetzt einfach mal an das ich ein Dictionary<int, string> habe. Der Key-Wert ist die Item Id, und der string die dazugehörige Bezeichnung.

    Kann ich jetzt statt der ItemId beim TextBlock direkt die Item Bezeichnung anzeigen lassen?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „seh“ ()

    Hallo

    seh schrieb:

    Das Projekt befindet sich hier


    Wenn du das gleich sagst hätte ich mir die ViewModels ansehen können!!

    seh schrieb:

    Kann ich jetzt statt der ItemId beim TextBlock direkt die Item Bezeichnung anzeigen lassen?

    Sicher,
    Angenommen (so habe ichs verstanden) du hast in der ViewModel Klasse wo jetzt die ID drinnen ist dein Dictionary.
    Dann machst du dir ein ReadOnly Property (aus den Kopf):

    VB.NET-Quellcode

    1. Public readOnly Property ItemTitle as string
    2. Get
    3. Return dictionary.Item(Me.ItemId)
    4. End Get
    5. End Property


    Und dann Bindest du einfach auf ItemTitle

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    Nofear23m schrieb:

    Wenn du das gleich sagst hätte ich mir die ViewModels ansehen können!!

    Ja dachte ich zuerst auch, aber da es im ViewModel doch nochmal komplizierter ist, als ich es jetzt erklärt habe, dachte ich wäre es vielleicht einfacher zu verstehen auf diese Weise.

    Zu meinem anderen Anliegen:
    Einläuchtend, supi, das klappt prima.