VB.Net-Forum - Beitragsübersicht -
ThemaV03: Komplexes Problem: Casting oder DataGrid
Von Stan
Datum 23. Februar 2016 um 22:53:31
Frage Hallo zusammen,

ich habe noch ein Thema bei dem ich einen Sparringspartner brauche.

Ich habe ein DataGrid, dass ich direkt an eine ObservableCollection gebunden habe. Die Collection ist von meinem Basistyp, sagen wir zur Vereinfachung, diese wäre vom Typ Fahrzeug. Nun gibt es mehrere Ableitungen wie z.B. Auto oder Flugzeug.

Meine Idee war, dass der User im Datagrid alle Fahrzeuge(Auto, Flugzeug, etc) sehen und bearbeiten kann. Anfäglich kann der User nur die Eigenschaften verändern, die alle gemeinsam besitzen, also Fahrzeug. Setzt der User einen Filter, beidem nur noch Autos übrg bleiben, so würde ich die ObservableCollection Casten und darauß Autos machen. Der User könnte sofort alle Eigenschaften eines Autos bearbeiten.
Hochdynamisch ;-)

Mein Problem ist das Anlegen einer neuen Zeile. Der User sollte die Art des Fahrzeugs über eine Dropdownliste auswählen können. Allerdings wird durch das DataGrid bereits beim Anklicken der neuen Zeile ein neues Objekt angelegt, dann vom Basistyp.

Zuerst wollte ich das Anlegen der neuen Zeile bis zur Auswahl des Typs via Combobox heruaszögern, aber ich glaube das DataGrid braucht den Eintrag zur Datenhaltung. => Hier bin aber offen für Lösungsvorschläge

Deshalb habe ich mich auf das Casten konzentriert, um die Objekte im Nachgang zu verändern. Ich weiß, dass ich
=> aus einem Child immer den Parent casten kann(Auto => Fahrzeug)
=> den so erstellen Parent wieder zum Child casten kann(Fahrzeug(Auto) => Auto)

Allerdings müsste ich ein reinen Parent zu einem beliebigen Child(Fahrzeug => Auto) "erweitern", beziehungsweise ein Child in ein anderes Child(Auto => Flugzeug) "umwandeln" können. Ich würde einen Datenverlust aller Childvariablen akzeptieren.

Irgendwelche Ideen?

Beste Grüße
Stan
Public Class Fahrzeug

Public geschwindigkeit As Integer

End Class

Public Class Auto
Inherits Fahrzeug

Public Allrad As Boolean

End Class

Public Class Flugzeug
Inherits Fahrzeug

Public maxFlughoehe As Long

End Class
Antwort:
Von Nico
E-Mail nico.schertler@studentpartners.de
Datum 03. März 2016 um 10:41:00
Antwort Hallo,

ich hatte an so etwas in der Art gedacht:
'XAML:
<DataGrid Name="dg" AutoGenerateColumns="True"/>

'Code Behind:
Imports System.Collections.ObjectModel
Imports System.Collections.Specialized

Class MainWindow

Dim transportMittel As New ObservableCollection(Of Transportmittel)

Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
dg.ItemsSource = New ObservableCollectionView(Of Transportmittel, Auto)(transportMittel)

transportMittel.Add(New Auto With {.Id = 0, .Marke = "Audi"})
transportMittel.Add(New Flugzeug With {.Id = 1, .Hersteller = "Boeing"})
transportMittel.Add(New Auto With {.Id = 2, .Marke = "BMW"})
End Sub
End Class

MustInherit Class Transportmittel
Public Property Id As Integer
End Class

Class Auto : Inherits Transportmittel
Public Property Marke As String
End Class

Class Flugzeug : Inherits Transportmittel
Public Property Hersteller As String
End Class

Public Class ObservableCollectionView(Of TBasis, TFilter As TBasis)
Implements ICollection(Of TFilter)
Implements INotifyCollectionChanged

Dim datenQuelle As ObservableCollection(Of TBasis)
Public Sub New(datenQuelle As ObservableCollection(Of TBasis))
Me.datenQuelle = datenQuelle
AddHandler datenQuelle.CollectionChanged, AddressOf datenQuelle_CollectionChanged
End Sub

Public ReadOnly Property Count As Integer Implements ICollection(Of TFilter).Count
Get
Return datenQuelle.Count
End Get
End Property

Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of TFilter).IsReadOnly
Get
Return CType(datenQuelle, ICollection(Of TBasis)).IsReadOnly
End Get
End Property

Public Event CollectionChanged As NotifyCollectionChangedEventHandler Implements INotifyCollectionChanged.CollectionChanged

Private Sub datenQuelle_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
If e.Action = NotifyCollectionChangedAction.Add Then
Dim tatsächlicheNeueElemente As New List(Of TFilter)
For Each item As TBasis In e.NewItems
If TypeOf item Is TFilter Then tatsächlicheNeueElemente.Add(item)
Next
If e.NewItems.Count > 0 Then
Dim args As New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, tatsächlicheNeueElemente)
RaiseEvent CollectionChanged(Me, args)
End If
End If
'Weitere Aktionen implementieren
End Sub

Public Sub Add(item As TFilter) Implements ICollection(Of TFilter).Add
datenQuelle.Add(item)
End Sub

Public Sub Clear() Implements ICollection(Of TFilter).Clear
datenQuelle.Clear()
End Sub

Public Sub CopyTo(array() As TFilter, arrayIndex As Integer) Implements ICollection(Of TFilter).CopyTo
Throw New NotImplementedException()
End Sub

Public Function Contains(item As TFilter) As Boolean Implements ICollection(Of TFilter).Contains
Return datenQuelle.Contains(item)
End Function

Public Function Remove(item As TFilter) As Boolean Implements ICollection(Of TFilter).Remove
Return datenQuelle.Remove(item)
End Function

Public Function GetEnumerator() As IEnumerator(Of TFilter) Implements IEnumerable(Of TFilter).GetEnumerator
Return New ObservableCollectionViewEnumerator(Of TBasis, TFilter)(datenQuelle)
End Function
Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return New ObservableCollectionViewEnumerator(Of TBasis, TFilter)(datenQuelle)
End Function
End Class

Public Class ObservableCollectionViewEnumerator(Of TBasis, TFilter As TBasis)
Implements IEnumerator
Implements IEnumerator(Of TFilter)

Dim baseEnumerator As IEnumerator(Of TBasis)
Public Sub New(datenQuelle As ObservableCollection(Of TBasis))
baseEnumerator = datenQuelle.GetEnumerator()
SucheNächstesElementMitPassendemTyp()
End Sub

Private Function SucheNächstesElementMitPassendemTyp() As Boolean
While Not TypeOf baseEnumerator.Current Is TFilter
If Not baseEnumerator.MoveNext() Then Return False
End While
Return True
End Function

Public ReadOnly Property Current As Object Implements IEnumerator.Current
Get
Return baseEnumerator.Current
End Get
End Property

Private ReadOnly Property IEnumerator_Current1 As TFilter Implements IEnumerator(Of TFilter).Current
Get
Return baseEnumerator.Current
End Get
End Property

Public Sub Reset() Implements IEnumerator.Reset
baseEnumerator.Reset()
End Sub

Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
If Not baseEnumerator.MoveNext() Then Return False
Return SucheNächstesElementMitPassendemTyp()
End Function

Public Sub Dispose() Implements IDisposable.Dispose
baseEnumerator.Dispose()
End Sub
End Class
Anstatt das DataGrid an die ObservableCollection zu binden, erstellst du ein ObservableCollectionView, die nur die Elemente mit dem entsprechenden Typ zurückgibt, und bindest es daran. Wichtig ist, dass in dieser Klasse die datenQuelle_CollectionChanged() richtig implementiert wird. Ich habe das jetzt nur für die Add-Aktion gemacht.
Im Beispiel wird ein View erstellt, der nur Autos aus der ObservableCollection herausfiltert. Durch diese starke Typisierung weiß das DataGrid dann auch, welche Spalten es anzeigen soll. Umgesetzt wird das durch die Implementierung von Implements ICollection(Of TFilter).
[ Antwort schreiben | Zurück zum VB.Net-Forum | Forum-Hilfe ]
Antworten
V03: Komplexes Problem: Casting oder DataGrid - Stan 23. Februar 2016 um 22:53:31
Re: Komplexes Problem: Casting oder DataGrid - Nico 24. Februar 2016 um 09:17:15
Re: Komplexes Problem: Casting oder DataGrid - stan 25. Februar 2016 um 20:01:21
Re: Komplexes Problem: Casting oder DataGrid - stan 01. März 2016 um 21:54:10
Re: Komplexes Problem: Casting oder DataGrid - Nico 01. März 2016 um 22:20:06
Re: Komplexes Problem: Casting oder DataGrid - Stan 01. März 2016 um 22:30:08
Re: Komplexes Problem: Casting oder DataGrid - stan 02. März 2016 um 21:53:36
Re: Komplexes Problem: Casting oder DataGrid - Nico 03. März 2016 um 10:41:00
Re: Komplexes Problem: Casting oder DataGrid - stan 05. März 2016 um 15:32:49
Re: Komplexes Problem: Casting oder DataGrid - Nico 06. März 2016 um 10:31:44
Re: Komplexes Problem: Casting oder DataGrid - stan 07. März 2016 um 21:32:20

Ihre Antwort
(Nick-)Name   Wichtige Informationen zur Namensangabe
E-Mail (opt.)  Wichtige Informationen zur Angabe einer eMail-Adresse
Thema   Wichtige Informationen zur Angabe eines Themas
Betrifft (IDE)  VB.Net 2003
Ihre Antwort
Smilies
Mehr...
FettKursivUnterstrichen   Übersicht der Tipp-KürzelÜbersicht der Projekt-KürzelÜbersicht der Bücher-Kürzel 
Homepage
Titel
Root-Smilies              
             
             
[ Zurück zum VB.Net-Forum | Forum-Archiv | Forum-Hilfe | Chat ]

Zum Seitenanfang

Startseite | VB-/VBA-Tipps | Projekte | Tutorials | API-Referenz | Komponenten | Bücherecke | Gewinnspiele | VB.Net | VB/VBA-Forum | DirectX | DirectX-Forum | Chat | Ausschreibungen | Links | Suchen | Stichwortverzeichnis | Feedback | Impressum

Seite empfehlen Bug-Report
Letzte Aktualisierung: Sonntag, 13. Dezember 2015