ObservableCollection<ViewModel> VS. ObservableCollection<Model>

  • WPF

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    ObservableCollection<ViewModel> VS. ObservableCollection<Model>

    Hallo,
    ich habe eine Grundsätzliche Frage zu obiger Problematik.
    ich weis nicht genau, wie ich es beschreiben soll.
    Ich habe ein VieModel Names EventListViewModel, dies ist das ViewModel für eine Liste aller Events und ist an ein Control in einer View gebunden.
    Die Liste an sich enthält Items als ObservableCollection vom Typ EventListItemViewModel da jedes Item dieser Liste auch sein eigenens ViewModel hat.

    Nun kann ich die Daten auslesen und in eine ObservableCollection packen, allerdings muss diese Collection vom gleichen Typ sein, wie das DBSet also der ModellTyp.
    Wie bekomme ich nun den Convert hin vom ModelTyp zum VieModeltyp.

    Vielleicht ein wenig Code:
    in meinem EventListViewModel gibt es:

    C#-Quellcode

    1. public ObservableCollection<EventListItemViewModel> UpcomingEvents { get; set; } //eine Liste für die Filterung
    2. public ObservableCollection<BazaarEvent> AllEvents { get; set; } //die Collection mit dem ModelTyp
    3. private ObservableCollection<EventListItemViewModel> _items;
    4. public ObservableCollection<EventListItemViewModel> Items
    5. {
    6. get => _items;
    7. set
    8. {
    9. if (_items == value) return;
    10. _items = value;
    11. UpcomingEvents = new ObservableCollection<EventListItemViewModel>(_items.Where(item => item.EventDate <= EventDateFilter).OrderBy(item => item.EventDate));
    12. }
    13. }
    14. //BazaarDaten für den Responsible laden
    15. AllEvents = _ctx.BazaarEvents
    16. .Include(rp => rp.ResponsiblePerson) //includieren, damit Zugriff auf die Details besteht (LogIn Daten, Name usw.)
    17. .ThenInclude(org => org.Organization) //danach includieren um Zugriff auf die Organisation Daten zu erhalten
    18. .Include(pe => pe.Sellers) //Sellers ist vom Typ ICollection<PersonBazaarEvent>, muss includiert werden um an die Verkäufer ran zu kommen
    19. .ThenInclude(p => p.Person) //von den Verkäufern includieren um auf die Details Zugriff zu bekommen (Name, Verkäufernummer usw.)
    20. .ThenInclude(a => a.Articles) //wiederum von der Person der Sellers includieren um auf desen Artikel Details zu kommen (Artikelnr., Beschreibung usw.)
    21. .AsNoTracking()
    22. .Where(p => p.ResponsiblePerson == person).ToObservableCollection(); //eigene Extension gebaut um die IQueryable in eine Observable zu casten
    23. //die Extension
    24. public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> iEnumerable)
    25. {
    26. return new ObservableCollection<T>(iEnumerable);
    27. }

    An dieser Stelle würde ich gerne mit Items weiterarbeiten und nicht mit AllEvents
    Bin für jeden Tip dankbar
    Grüße
    "Hier könnte Ihre Werbung stehen..."
    Hallo

    Du hast es schon gut genug beschrieben.

    Da ich mit C# immernoch etwas am Kriegsfuß bin habe ich dir ein Vb Beispielprojekt erstellt. Ich finde Anhand eines Beispiels kann an es immer besser nachvollziehen.

    Trotzdem hier ein Auszug:

    Ich habe in dem Beispiel zwei Models. Fahrzeuge und deren Ausstattung.

    Im ViewModel sieht das dann so aus:

    VB.NET-Quellcode

    1. Public Class AllVehiclesWorkspace
    2. Inherits ViewModelBase
    3. Public Sub New()
    4. 'Alle Fahrzeuge als Model-Liste
    5. Dim vehicles As List(Of Model.Vehicle) = New DAL.FakeDal().GetVehiclesIncludeEquipments
    6. 'Nun muss jedes Modelobjekt in ein ViewModel Objekt gewandelt werden...
    7. 'Dafür gibt es den zweiten Konstruktor in VehicleViewModel
    8. vehicles.ForEach(Sub(x) AllVehicles.Add(New VehicleViewModel(x)))
    9. End Sub
    10. Private _AllVehicles As New ObservableCollection(Of VehicleViewModel)
    11. Public Property AllVehicles As ObservableCollection(Of VehicleViewModel)
    12. Get
    13. Return _AllVehicles
    14. End Get
    15. Set
    16. _AllVehicles = Value
    17. RaisePropertyChanged()
    18. End Set
    19. End Property
    20. Private _SelectedVehicle As VehicleViewModel
    21. Public Property SelectedVehicle As VehicleViewModel
    22. Get
    23. Return _SelectedVehicle
    24. End Get
    25. Set
    26. _SelectedVehicle = Value
    27. RaisePropertyChanged()
    28. End Set
    29. End Property
    30. End Class


    VB.NET-Quellcode

    1. Public Class VehicleViewModel
    2. Inherits ViewModelBase
    3. 'Mit diesem 'originalem' Modelobjekt wird gearbeitet
    4. 'Die Properties des VM geben nur den Wert der Properties dieses Objekts zurück bzw. speichern wieder in dieses
    5. 'Bis auf die Observable, dort gehts nicht direkt (siehe unten)
    6. Private ReadOnly _vehicleModelObject As Model.Vehicle
    7. Public Sub New()
    8. _vehicleModelObject = New Vehicle
    9. _vehicleModelObject.Equipments = New List(Of Model.Equipment)
    10. End Sub
    11. Friend Sub New(vehicle As Model.Vehicle)
    12. _vehicleModelObject = vehicle
    13. 'Die ObservableCollection füllen (aber mit VMs) und Handler setzen
    14. If _vehicleModelObject.Equipments Is Nothing Then _vehicleModelObject.Equipments = New List(Of Model.Equipment)
    15. _vehicleModelObject.Equipments.ToList.ForEach(Sub(x) Equipments.Add(New EquipmentViewModel(x)))
    16. AddHandler Equipments.CollectionChanged, AddressOf EuqipmentList_Changed
    17. End Sub
    18. Private Sub EuqipmentList_Changed(sender As Object, e As NotifyCollectionChangedEventArgs)
    19. Select Case e.Action
    20. Case NotifyCollectionChangedAction.Add
    21. Exit Select 'hier das neue Objekt dem ModelObject hinzufügen
    22. Case NotifyCollectionChangedAction.Remove
    23. Exit Select 'hier das entfernte Objekt vom ModelObjekt entfernen
    24. End Select
    25. End Sub
    26. Public Property Manfacturer As String
    27. Get
    28. Return _vehicleModelObject.Manfacturer
    29. End Get
    30. Set
    31. _vehicleModelObject.Manfacturer = Value
    32. RaisePropertyChanged()
    33. End Set
    34. End Property
    35. Public Property Model As String
    36. Get
    37. Return _vehicleModelObject.Model
    38. End Get
    39. Set
    40. _vehicleModelObject.Model = Value
    41. RaisePropertyChanged()
    42. End Set
    43. End Property
    44. Private _Equipments As New ObservableCollection(Of EquipmentViewModel)
    45. Public Property Equipments As ObservableCollection(Of EquipmentViewModel)
    46. Get
    47. Return _Equipments
    48. End Get
    49. Set
    50. _Equipments = Value
    51. RaisePropertyChanged()
    52. End Set
    53. End Property
    54. Public Overrides Function ToString() As String
    55. Return $"{Manfacturer} {Model}"
    56. End Function
    57. End Class


    VB.NET-Quellcode

    1. Public Class EquipmentViewModel
    2. Inherits ViewModelBase
    3. 'Mit diesem 'originalem' Modelobjekt wird gearbeitet
    4. 'Die Properties des VM geben nur den Wert der Properties dieses Objekts zurück bzw. speichern wieder in dieses
    5. Private ReadOnly _equipmentModelObject As Model.Equipment
    6. Public Sub New()
    7. _equipmentModelObject = New Model.Equipment
    8. End Sub
    9. Public Sub New(equipment As Model.Equipment)
    10. _equipmentModelObject = equipment
    11. End Sub
    12. Public Property Name As String
    13. Get
    14. Return _equipmentModelObject.Name
    15. End Get
    16. Set
    17. _equipmentModelObject.Name = Value
    18. RaisePropertyChanged()
    19. End Set
    20. End Property
    21. Public Property Price As Decimal
    22. Get
    23. Return _equipmentModelObject.Price
    24. End Get
    25. Set
    26. _equipmentModelObject.Price = Value
    27. RaisePropertyChanged()
    28. End Set
    29. End Property
    30. Public Overrides Function ToString() As String
    31. Return $"{Name} {Price.ToString} €"
    32. End Function
    33. End Class



    Ich hoffe das passt dir.

    Grüße
    Sascha
    Dateien
    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. ##

    Hi Sascha,
    Danke Dir... ich bin doof... ich hab doch in meiner ViewModelBase sogar eine Klasse BaseViewModel<TModel> : BaseViewModel, IViewModel<TModel> where TModel : class drin, die dafür geeignet sein soll.... Uff, dann muss ich ein wenig umbauen...

    Danke Dir, das Beispeil war einleuchtend, jetzt weis ich auch, wofür du die Workspaces benötigst. ist im WPF Notes 2 Projekt ja auch so gemacht....
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    drin, die dafür geeignet sein soll

    Das ist natürlich der sauberste Weg.
    Ich machs aber meisst über den Konstruktor da ich hier auch wenn es nötig ist mehrere Models übergeben könnte, oder gar Tuples.

    ist im WPF Notes 2 Projekt ja auch so gemacht

    Genau. da ist es auch so drinnen. Wollte aber ein Beispiel erstellen welches sich auf das wesentliche beschränkt.

    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. ##

    Ja, das Beispiel war perfekt, hab glaub auch im Moment Tomaten auf den Augen...
    Ich baue mir gerade erstmal Workspaces für die Dinge die ich brauche, und nehme vorerst das "normale" BaseViewModel und arbeite dann mit dem Konstruktor.

    Danke Dir, ich melde mich sicherlich wieder.
    "Hier könnte Ihre Werbung stehen..."