BS.CurrentChange Event führt zu RowNotInTableException

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von ludl8615.

    BS.CurrentChange Event führt zu RowNotInTableException

    Hallo,
    Hier wurde mir ja schon des Öfteren auf die Sprünge geholfen!! :thumbsup:
    Ich habe an DGVs Daten gebunden und schiebe spezielle Date in ein List(Of ) um verschiedene Vergleiche durchzuführen. Warum genau, ist ja erstamal egal, die List(Of ) bietet sich einfach an..

    Als Auslöser zum Füllen, Bearbeiten etc., dient mir das BindingSource.CurrentChange-Event:

    VB.NET-Quellcode

    1. Private Sub Gewicht_Anordnungsliste(sender As Object, e As EventArgs) Handles ProjLaststufenBindingSource.CurrentChanged, ProjLS_ProjGewichteBindingSource.CurrentChanged


    Function zum befüllen:

    VB.NET-Quellcode

    1. Private Function Fill_ListOfGewichte(ByVal LaststufenID_Ende As Integer) As Boolean
    2. Dim counter As Integer = 0
    3. MyGewichtListe.Clear()
    4. For Each LS_Row As ProjektDS.ProjLaststufenRow In ProjektDS.ProjLaststufen
    5. Dim GewichteInRow As Integer = 0
    6. For Each LS_Gew_Row As ProjektDS.ProjLS_ProjGewichteRow In ProjektDS.ProjLS_ProjGewichte
    7. If LS_Gew_Row.LS_ID = LS_Row.ID Then ' wenn LaststufenID in LS_Gewichte
    8. For Each GewRow As ProjektDS.ProjGewichteRow In ProjektDS.ProjGewichte
    9. If LS_Gew_Row.G_ID = GewRow.ID Then ' wenn GewichteID gleich der GewichteID in LS_Gewichte Tabelle
    10. GewichteInRow += 1
    11. If LS_Row.Entlastung Then ' Wenn Entlasten gewählt
    12. If Not Search_N_Delete_inListOF(MyGewichtListe, GewRow.ID) Then ' wenn Gewicht nicht auf dem Stapel vorhanden
    13. counter += 1
    14. MyGewichtListe.Add(New GewichtList() With {.Position = counter, .ID = GewRow.ID, .Farbe = GewRow.Farbe, .Gewicht_anzahl = GewichteInRow, .Fehler = True})
    15. Return False
    16. Else counter -= 1 ' Wenn Gewicht vorhanden, aus der List(Of ...) löschen und d.d. nicht in LV anzeigen.
    17. End If
    18. Else ' Wenn Belastung gewählt
    19. counter += 1
    20. MyGewichtListe.Add(New GewichtList() With {.Position = counter, .ID = GewRow.ID, .Farbe = GewRow.Farbe, .Gewicht_anzahl = GewichteInRow, .Fehler = False})
    21. End If
    22. End If
    23. Next
    24. End If
    25. Next
    26. If LS_Row.ID = LaststufenID_Ende Then Return True
    27. Next
    28. Return True
    29. End Function
    (Zwischenschritte lass ich jetzt mal der Übersichtshalber weg)
    Soweit macht es alles was es soll. Nur leider wird das Event ja auch ausgelöst wenn ich im DGV mit der dazugehörigen BS: ProjLS_ProjGewichteBindingSource, eine Row manuell lösche (also Zeile markieren und Taste Entf. ;) ). Und genau das führt Im DataSet.Designer zur Fehlermeldung: Diese Zeile wurde aus einer Tabelle entfernt und enthält keine Daten. BeginEdit() ermöglicht das Erstellen von neuen Daten in dieser Zeile. Verantwortliche Zeile im Code ist:
    If LS_Gew_Row.G_ID = GewRow.ID Then ' wenn GewichteID gleich der GewichteID in LS_Gewichte Tabelle
    Genauer => GewRow.ID

    Ich hab schon alles mir erdenkliche und im Netz auffindbare ausprobiert um dieses Problem zu umschiffen. Am liebsten wäre es mir, wenn "Row löschen - Event" dann Sub verlassen.
    Auch GewRow.HasError bringt nichts. Außerdem hab ich noch mit den DGV-Events probiert, aber das stellt mich nicht zufrieden, da diese Events nicht auslösen wenn ich es brauche und somit wird alles nur unsinnig und unnötig Kompliziert/unübersichtlich.

    Kennt jemand noch eine Lösung oder hat evtl. einen Verbesserungsvorschlag!?

    Vielen Dank!!!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ludl8615“ ()

    Ich blick zwar die Namensgebung überhaupt nicht und die komplexe 3-fach-Schleife verursacht Augenkrämpfe, aber ich versuch's mal. Ich vermute mal, dass die Gewicht_Anordnungsliste-Sub (also der EventHandler für die BindingSource-Events) jene Funktion Fill_ListOfGewichte aufruft. Dies geht nicht explizit aus Deinem Post hervor, daher: Stimmt meine Vermutung?

    Das Problem kann man einfach(er) nachstellen:

    VB.NET-Quellcode

    1. Private Sub BindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles BindingSource.CurrentChanged
    2. For Each Row In Tds.MyTable'.Where(Function(x) x.RowState = DataRowState.Added)
    3. If Row.ID = 0 Then Stop
    4. Next
    5. End Sub

    Rebelliert beim Löschen mit der von Dir erwähnten Exception. Mit dem Where-Zusatz geht es gut. Ist es sauber? Gute Frage. Du kannst auch zwischen Zeile#8* und #9 eine If-Abfrage machen, wo Du schaust, wie der aktuelle Zustand der Row ist und diese per Continue For überspringen.

    *eine Zeilennummer anzugeben ist besser als die Zeile selber. Die muss mal sonst nämlich erstmal im geposteten Quellcode suchen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Hallo.

    VaporiZed schrieb:

    Ich blick zwar die Namensgebung überhaupt nicht
    Ja, könnte man anders benennen. Teilweise auch vorhin schon passiert. LS_Row und LS_GEW_Row etc. ist eigentlich recht logisch, wenn man das DataSet etwas kennt. Aber Grundsätzlich stimm ich dir zu, geht besser. Daran arbeite ich.. ;)

    VaporiZed schrieb:

    3-fach-Schleife verursacht Augenkrämpfe
    Tatsächlich kenne ich noch keinen einfacheren Weg, alle DataTables mit einer n:m Beziehung zu Durchlaufen, um die passenden Daten in eine List(Of...)/Array/... zu schieben. Jedenfalls kenne ich keinen "bewusst"..

    VaporiZed schrieb:

    Ich vermute mal, dass die Gewicht_Anordnungsliste-Sub (also der EventHandler für die BindingSource-Events) jene Funktion Fill_ListOfGewichte aufruft. Dies geht nicht explizit aus Deinem Post hervor, daher: Stimmt meine Vermutung?
    Sehr richtig!!!


    Ich muss mich übrigens verbessern!!! Zeile #7 ist das Problem, also LS_Gew_Row.LS_ID :S :S

    VaporiZed schrieb:

    Du kannst auch zwischen Zeile#8* und #9 eine If-Abfrage machen, wo Du schaust, wie der aktuelle Zustand der Row ist und diese per Continue For überspringen
    Das hatte ich (In dem Fall jetzt zwischen #6 und #7) mit:If LS_Gew_Row.RowState = DataRowState.Deleted Then Continue For auch schon probiert. Keine Reaktion.

    Wenn ich den Inneren Teil, inklusive Zeile #7 auskommentiere läuft die Sache ohne Probleme. Sobald ich Zeile #7 dazu nehme taucht der Fehler auf. Also wenn ich Daten aus der Child-Tabelle lösche. Und die passende Row dazu ist ja LS_Gew_Row (Siehe Anhang).

    so funktioniert es:

    VB.NET-Quellcode

    1. Private Function Fill_ListOfGewichte(ByVal LaststufenID_Ende As Integer) As Boolean
    2. Dim counter As Integer = 0
    3. MyGewichtListe.Clear()
    4. For Each LS_Row As ProjektDS.ProjLaststufenRow In ProjektDS.ProjLaststufen
    5. Dim GewichteInRow As Integer = 0
    6. For Each LS_Gew_Row As ProjektDS.ProjLS_ProjGewichteRow In ProjektDS.ProjLS_ProjGewichte
    7. ' If LS_Gew_Row.RowState = DataRowState.Deleted Then Continue For ' Funzt nicht!!!!!!!
    8. ' If LS_Gew_Row.LS_ID = LS_Row.ID Then ' wenn LaststufenID in LS_Gewichte
    9. ' End If
    10. Next
    11. If LS_Row.ID = LaststufenID_Ende Then Return True
    12. Next
    13. Return True
    14. End Function




    Vielen Dank schon Mal!!!!!!!!!!!!!!!!
    Bilder
    • Unbenannt.JPG

      71,23 kB, 1.252×335, 10 mal angesehen
    Naja, es gibt aber mehr Row-Zustände als Added und Deleted. Daher hatte ich in der Where-Klausel auch angegeben, dass nur die durchlaufen werden sollen, die im Zustand Added sind. Du hingegen schließt nur die aus, die Deleted sind. Aber irgendwie glaube ich, dass Du alle ausschließen solltest, die nicht Added sind. Das schließt zwar Deleted mit ein, aber eben auch andere. Probier's mal.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Also,.. Das Schlüsselwort lautet Detached. Ich weiß gar nicht warum ich es nicht schon vorher einfach mal probiert hatte, aber wahrscheinlich hatte ich auch zeitweise versehentlich eine Row der Parent Table im Auge, was natürlich Quatsch war. Ich hatte mir nämlich RowState über die Konsole ausgeben lassen und kurz vor dem Fehler keine Änderung feststellen können. Deshalb meine Vermutung.
    Und jaaa,... ich weiß. Eindeutigere Namensvergebung kann helfen!

    Mit:

    VB.NET-Quellcode

    1. If LS_Gew_Row.RowState = DataRowState.Detached Then Continue For
    funktioniert es tadellos!

    Vielen Dank nochmal für den Denkanstoß!! Hatte wiedermal viel zu lange mit so einer Kleinigkeit verbummelt, aber jetzt kenne ich auch diese Methode und hab auch daraus was gelernt. ;)

    Schönen Gruß!