ComboBox mittels DataTemplate mit Propertys einer Klasse füllen

  • WPF

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    ComboBox mittels DataTemplate mit Propertys einer Klasse füllen

    Tach allerseits,

    nachdem ich nun 2-3 Tage so klargekommen bin, brauch ich mal wieder Hilfe.

    Ich gehe gerade das Kapitel 2.1.1.2 des WPF Tutorials von @Nofear23m durch und versuche, das Beispiel auf meine Bedürfnisse anzupassen. Wie der Titel schon verrät, möchte ich eine ComboBox mittels DataTemplate mit Daten füllen. Hierzu hab ich mir eine Klasse Genres geschrieben, die die Propertys Genre und Vorhanden hat:

    VB.NET-Quellcode

    1. Public Class Genres
    2. Public _Vorhanden As Boolean
    3. Public _Genre As String
    4. Public Property Vorhanden As Boolean
    5. Get
    6. Return _Vorhanden
    7. End Get
    8. Set(value As Boolean)
    9. _Vorhanden = value
    10. End Set
    11. End Property
    12. Public Property Genre As String
    13. Get
    14. Return _Genre
    15. End Get
    16. Set(value As String)
    17. _Genre = value
    18. End Set
    19. End Property
    20. Public Sub New(varVorhanden As Boolean, varGenre As String)
    21. _Vorhanden = varVorhanden
    22. _Genre = varGenre
    23. End Sub
    24. End Class


    Diese Daten möchte ich folgendermassen in einer ComboBox darstellen:

    XML-Quellcode

    1. <ComboBox ItemsSource="{Binding Musikgenres}">
    2. <ComboBox.ItemTemplate>
    3. <DataTemplate>
    4. <CheckBox Content="{Binding Path=Genre}" IsChecked="{Binding Path=Vorhanden}"/>
    5. </DataTemplate>
    6. </ComboBox.ItemTemplate>
    7. </ComboBox>


    Die "Datenliste" befülle ich folgendermassen (das hab ich ausprobiert, das klappt so:

    VB.NET-Quellcode

    1. Class MainWindow
    2. Public Musikgenres As New ObservableCollection(Of Genres)
    3. Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    4. Musikgenres.Add(New Genres(True, "Hiphop"))
    5. Musikgenres.Add(New Genres(False, "R&B"))
    6. Musikgenres.Add(New Genres(True, "Rock/Pop"))
    7. End Sub
    8. End Class


    Wenn ich das Programm jetzt starte, kommt zwar kein Fehler, aber die ComboBox bleibt leer. Hat mir jemand einen Tipp, denn ich glaube ich suche wie so oft an der falschen Stelle (meine Vermutung ist, dass irgendwas mit dem Binding in dem XAML-Code nicht stimmt).
    Hallo

    Ich muss es nochmals sagen.
    Es bringt dir nix ein Kapitel rauszusuchen. Du solltest die nach und nach durchgehen, das merkt man weil du hier in dem Beispiel viel "vergessen" hast.

    Du wirfst in den Settern der Properties kein NotifyPropertyChanged. Ist nicht wild solange du keine Daten manipulierst, aber dann brauchst du ja auch keine Eigenschaft mit Getter und Setter. In dem Fall reicht ja dann ein:

    VB.NET-Quellcode

    1. ​Public Property Genre As String


    Weiters kann nichts angezeigt werden solange du keinen Datenkontext setzt. Die WPF weis ja jetzt garnicht von wo die Daten für die Combobox kommen sollen.

    Also muss mal ins MainWindow_Loaded noch folgendes rein: Me.DataContext = Musikgenres​

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

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    ErfinderDesRades schrieb:

    Ich würde beim DataTemplate immer den Datentyp angeben

    Gebe ich dir recht, ist eine Stilfrage, ich gebs auch fast immer mit an, funzt in dem Fall aber ohne auch.

    ErfinderDesRades schrieb:

    Dann wundere ich mich auch, das im ItemTemplate einer Combobox eine Checkbox-Property gebunden werden kann

    Naja, das ItemTemplate steht ja für sich, dem ist also egal in welchem Container es sich befindet. Das ist völlig getrennt. Ein Template eben. Der DatanKontext wird in das Template vererbt und dann kann innerhalb des Templates jedes Element Binden wie es will.

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

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m

    So, ist ne Weile her, dafür möchte ich mich erstmal entschuldigen. Hatte wenig Zeit und Kopf zum Programmieren, jetzt sitz ich seit Längerem mal wieder dran...

    Ich hab alles so gemacht wie du es sagst (zumindest glaube ich das), nur scheint, wenn ich etwas an Musikgenres ändere, keine Änderung gefeuert zu werden (die MessageBox ist zu Testzwecken da drin):

    VB.NET-Quellcode

    1. Public Class Genres
    2. Implements ComponentModel.INotifyPropertyChanged
    3. Public _Vorhanden As Boolean
    4. Public _Genre As String
    5. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    6. Public Property Vorhanden As Boolean
    7. Get
    8. Return _Vorhanden
    9. End Get
    10. Set(value As Boolean)
    11. _Vorhanden = value
    12. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Vorhanden"))
    13. MessageBox.Show("Test")
    14. End Set
    15. End Property
    [...]

    XML-Quellcode

    1. <CheckBox Content="{Binding Path=Genre, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsChecked="{Binding Path=Vorhanden, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>


    Ich probier jetzt schon seit drei Stunden rum, und hab mir die entsprechenden Teile deines Videos (2.1.4.2) mehrmals angesehen, aber irgendwas übersehe ich...
    @ErfinderDesRades

    Ja man muss dazu sagen, ich hab das spaßeshalber mal einfach versucht mit MeineCombobox.ItemsSource = Musikgenres im Code Behind versucht. Da werden die Items sogar in zweifacher Ausführung angezeigt. Warum auch immer. Wenn ich da richtig denke schliesst diese Tatsache ein Problem mit dem Binding aus oder? Wie gesagt aus irgend einem Grund wird beim Adden von Items zu Musikgenres das Ereignis im Setter nicht ausgelöst... Besteht evtl. ein Unterschied zwischen dem Adden von Items über einen Konstruktor mit Werten für die Properties und dem direkten Setzen von Properties?

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

    kafffee schrieb:

    versucht mit MeineCombobox.ItemsSource = Musikgenres im Code Behind
    CodeBehind ist genau was man nicht machen sollte.
    Wozu bindest du im Wpf-Designer, wennde im CodeBehind dann wieder mit was annerem drüberbügelst?

    Items in zweifacher Ausführung kann ich mir grad nicht vorstellen
    @ErfinderDesRades

    Ja genau deswegen wie gesagt spaßeshalber. Hab ich bloss mal ausprobiert mit dem Ziel das ganze zu testen ob das generell funktioniert. Für meine Zwecke brauch ich das Ganze eh im Mode = TwoWay...

    Vom MVVM versuch ich mich gerade bewusst noch ein bisschen fernzuhalten, das ist mein erstes WPF-Projekt und bin noch bisschen in der Phase zu testen was geht und was eben nicht. Dieses Problem was ich hier hab ist das allererste Mal dass ich überhaupt das DataBinding in zwei Richtungen praktiziere... Und arbeite mich gerade durch die Videos vom Sascha Patschka durch, aber da kann es sein dass ich mal ein Detail vergesse. Die Videos sind zwar gut aber ja teilweise recht lang (soll jetzt keine Kritik sein, nur eine Feststellung wie ich das empfinde)..

    kafffee schrieb:

    Vom MVVM versuch ich mich gerade bewusst noch ein bisschen fernzuhalten
    Kann ich nicht recht verstehen. Ich sehe MVVM als Kern und Einstiegspunkt ins WPF - nichts, was man vertagt oder vor sich herschiebt.
    Ohne MVVM ergibt Wpf gar keinen Sinn, und ist nur ein Sammelsurium von dolle Klickibunti - allerdings überaus umständlich und anfällig.
    Erst MVVM bietet eine sinnvolle Anwendungsstruktur für grosse und kleine Projekte, wo GUI und Daten klar getrennt sind, und wo einigermassen klar geregelt ist, welche Anforderung wo codemässig umgesetzt wird.
    @Nofear23m

    Ich glaube ich hab den Fehler gefunden... Wie du siehst hab ich die Protected Overridable Sub RaisePropertyChanged weggelassen. Ich hab das RaiseEvent PropertyChanged direkt in den Setter geschrieben. Aus folgenden Gründen:

    1. Das <CallerMemberName> wie in deinem Video wird bei mir vom Editor nicht angenommen.
    2. Ich hab nicht genau verstanden, warum man das RaiseEvent PropertyChanged jetzt in eine extra Sub packen muss.

    Hab mir dann einfach nichts dabei gedacht...

    Kannst du mir erklären warum man das in eine extra Sub packen muss und v.a. wie ich das mit dem <CallerMemberName> hinbekomme? Ich benutze Framework 4.6.1...

    @ErfinderDesRades

    Ich hab mich für die WPF entschieden gerade wegen diesen Klickibunti-Effekten... Damals wusste ich aber auch noch nicht (und ehrlich gesagt immer noch nicht) was alles möglich ist mit WPF.

    Ich dachte der einzige Unterschied wäre, dass man halt das UI in XAML beschreibt.

    Ich halte mich jetzt hauptsächlich an das Tutorial von NoFear23m, und da bin ich jetzt schlichtweg noch nicht bei MVVM angekommen. Ich hab mir das aber schon mal im Voraus ein bisschen angeschaut bevor ich jetzt anfang gross zu programmieren und irgendwas zu konzipieren aber hab nicht wirklich verstanden was jetzt MVVM anders macht. Weil die UI und den Code Behind hab ich ja schon getrennt, oder? Und was ist MVVM konkret? Hab mich zwar informiert im Internet, hab aber auf meine Frage keine Antwort rauslesen können, wahrscheinlich weil mir das Grundwissen noch fehlt. Deswegen eins nach dem Andern...

    Edit:
    @Nofear23m

    Hat sich erledigt. Ich habs hinbekommen via:

    VB.NET-Quellcode

    1. Private Sub OnPropertyChanged(ByVal info As String)
    2. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
    3. End Sub


    Der Grund dafür, dass die Items in zweifacher Ausführung angezeigt wurden, lag daran, dass das Event MainWindow_Loaded() aus irgendeinem Grund zweimal gefeuert wurde, auch wenn ich nicht verstehe warum... Auch das Binding selbst hab ich bloss via Code Behind (MeineCombobox.ItemsSource = Musikgenres) hinbekommen :(

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kafffee“ ()