Laden...

Wie im Datagrid für jeden Eintrag einer Collection eine Spalte mit Combobox anzeigen & füllen?

Erstellt von GeneVorph vor 3 Jahren Letzter Beitrag vor 3 Jahren 469 Views
G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren
Wie im Datagrid für jeden Eintrag einer Collection eine Spalte mit Combobox anzeigen & füllen?

Hallo,

ich stecke gerade bei folgendem Problem fest:

ich habe ein DataGrid, dessen ItemsSource eine ObservableCollection<Instrument> in meinem ViewModel ist.

Beim Typ 'Instrument' handelt es sich um Saiteninstrumente. 'Instrument' hat ein Property namens 'InstrumentType' (z. B. Gitarre, Bass, Ukulele...).

Nun möchte ich, dass im Datagrid für jeden Eintrag in meiner Collection eine Spalte mit einer ComboBox angezeigt wird, die verschiedene Saitensätze beinhaltet. Welche Saitensätze angezeigt werden, hängt von InstrumentType ab.

Um es einfach zu machen: so gibt es für den InstrumentType "AcousticGuitar", z. B. eine ObservableCollection<StringSet> AcousticGuitarStringSets, in der alle in Frage kommenden Saitensätze hinterlegt sind.

Konkret hänge ich dabei im XAML-Code - ich hatte an so etwas gedacht:


<DataGridTemplateColumn>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox>
                                    <Style TargetType="ComboBox">
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Findancestor, AncestorType={x:Type Window}}, Path=DataContext.SelectedInstrument.InstrumentType}" Value="AcousticGuitar">
                                                <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AcousticGuitarStringSets}"/>
                                            </DataTrigger>
                                            
                                        </Style.Triggers>
                                    </Style>
                                </ComboBox>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>

Ich muss dazu sagen, dass ich bei

<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.AcousticGuitarStringSets

vollkommen geraten habe. Für alles, was ich nach DataContext eingebe bekomme ich auch keine InteliSense-Vorschläge. Möglicherweise gehe ich das Problem falsch an.

Für Ratschläge schonmal vielen Dank!

Gruß
Vorph

W
955 Beiträge seit 2010
vor 3 Jahren

Du könntest alternativ den jeweiligen Saitensatz in der Instrument-Klasse halten von dem der Benutzer eines auswählt. Oder besser noch mit einem InstrumentViewModel arbeiten. Also ohne RelativeSource arbeiten sondern direkt am Listenobjekt binden.
InstrumentViewModel kennt das Instrument und weiß anhand dessen Typs welche Saitenliste dafür in Betracht kommt. Vllt mit Overriding arbeiten.

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren

Du könntest alternativ den jeweiligen Saitensatz in der Instrument-Klasse halten von dem der Benutzer eines auswählt. .

Ja, im Prinzip schon - aber das hätte IMHO einen "Schönheitsfehler": damit müsste jedes Instrument mit allen möglichen Saitensätzen gefüllt werden, immer dann z. B., wenn ein Saitensatz neu hinzukommt; und der müsste dann bei allen Instrumenten in der Datenbank geupdated werden, wann immer dies der Fall wäre.

Insofern wäre es besser, wenn beim Befüllen des Grids einfach ein entsprechender Verweis anhand des InstrumentTypes auf die jeweilige ObservableCollection im ViewModel vollzogen würde.

Auch das Instrument- und StringSet-Object lassen sich viel besser verwalten, wenn sie nicht implizit miteinander verschränkt sind (will heißten b ist Property von a).
Trotzdem: vielen Dank für den Input, witte!

Jemand ne Idee zur Umsetzung des ursprünglichen Vorhabens?

W
955 Beiträge seit 2010
vor 3 Jahren

Du sollst das nicht in die Datenbank schreiben, sondern im ViewModel die Collection zum Lesen vorhalten die für den jeweiligen Typen vonnöten ist. Ein InstrumentViewModel bekommt im Konstruktor sein Modell injiziert und zusätzlich die Liste an Saitendingern die es zur Auswahl braucht - oder es filtert diese sich selbst heraus. Dazu ist das ViewModel schließlich da - das die Daten nicht so präsentiert werden müssen wie sie im Modell definiert wurden.

G
GeneVorph Themenstarter:in
180 Beiträge seit 2015
vor 3 Jahren

Du sollst das nicht in die Datenbank schreiben, sondern im ViewModel die Collection zum Lesen vorhalten die für den jeweiligen Typen vonnöten ist. Ein InstrumentViewModel bekommt im Konstruktor sein Modell injiziert und zusätzlich die Liste an Saitendingern die es zur Auswahl braucht - oder es filtert diese sich selbst heraus. Dazu ist das ViewModel schließlich da - das die Daten nicht so präsentiert werden müssen wie sie im Modell definiert wurden.

Verstehe - war'n Missverständnis.

Ich habe festgestellt, dass es auf StackOverflow ein paar Einträge dazu gibt, z. B. hier. Die Lösung schaut eigentlich ähnlich aus, wie das, was ich bereits erarbeitet hatte. Ich verstehe nur nicht, wo in meinem Code der Fehler liegt...

W
955 Beiträge seit 2010
vor 3 Jahren

Ja das Problem ist aber dass du die Aufzählung dynamisch brauchst und du wirst dir auf xaml-Ebene dabei einen abbrechen. Möglicherweise bekommst du das mit DataTriggern, Selektoren und CollectionViews gebacken - bei jeder Änderung und Erweiterung jedoch fällt das Kartenhaus zusammen. Musst du entscheiden welchen Weg du gehst - ich würde mit meinen Erfahrungen das auf ViewModel-Ebene lösen.