Problem bei TableAdapter.Update mit DataGridView und Detailansicht

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Zeus_EA.

    Problem bei TableAdapter.Update mit DataGridView und Detailansicht

    Guten Abend alle zusammen. Ich habe vor einigen Tagen begonnen mich mit der VB-Programmierung zu befassen.
    Nun bin ich erstmals auf ein Problem gestoßen, welches ich vermutlich nicht in Eigenrecherche lösen kann. Daher möchte ich es gerne auf diesen Weg versuchen.

    Also ich habe eine Access-Datenbank deren Daten per DataSet in eine Windows-Forms-Anwendung geladen werden.
    Das betroffene Formular "frmDebitoren" enthält ein DataGridView, einen Detailbereich und einen Button "Speichern" (cmdSpeichern).

    Der DataGridView ist eine Debitorenübersicht (aus 2 Spalten). Beim Auswählen eines Debitoren im DataGridView sieht man in der Detailansicht alle Angaben für diesen.

    Wenn man nun einen Wert im Textfeld des Detailbereichs ändert, und auf "Speichern" klickt, soll nun der DataGridViewer aktualisiert werden und der geänderte Wert in die Datenbank geschrieben werden/geändert werden. Und genau dabei habe ich ein Problem!
    1.) Bleibt man in der geänderten Textbox "Debitor_IDTextBox" stehen und drückt "Speichern" aktualisiert sich der Wert im DataGridView nicht. Der Wert wird auch nicht in die Datenbank geschrieben.
    2.) Hat man die Textbox "Debitor_IDTextBox" geändert und navigiert per TAB in die nächste Textbox ändert sich zwar der Wert in der DGV, wird jedoch nicht in die Datenbank geschrieben.
    3.) Der Wert wird lediglich in in die Datenbank geschrieben, wenn man in dem DGV in eine andere Datenzeile klickt und dann erst auf speichern

    Hier der Code des Speichern Buttons:

    VB.NET-Quellcode

    1. Private Sub cmdSpeichern_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSpeichern.Click
    2. Dim DebitorRow As _DatenbankDataSet.tblDebitorenRow
    3. DebitorRow = _DatenbankDataSet.tblDebitoren.FindByDebitor_ID(Debitor_IDTextBox.Text)
    4. DebitorRow.Debitor_Name1 = Debitor_Name1TextBox.Text
    5. Me.TblDebitorenTableAdapter.Update(Me._DatenbankDataSet.tblDebitoren)
    6. End Sub


    Der Code ist ersteinmal abgespeckt auf das Ändern des Wertes "Debitor_Name1"

    Kann mir evtl. jemand dieses Problem erklären, bzw. einen Hinweis geben, wie ich meinen Code ändern muss, damit ich nicht erst jedes mal in der DGV einen anderen Datensatz auswählen muss, bevor man "Speichern" drücken kann?


    Vielen, vielen Dank bereits im Voraus!
    Its no bug - its a feature!

    ADO.Net ist der Ansicht, dasses unnötiger DB-Traffic wäre, wenn man jede einzelne Änderung gleich in die DB schriebe. Im Grunde kann dein "Speichern" - Button weg, oder er kann eine ganz annere Bedeutung bekommen.
    Nämlich, dass alle Änderungen, die seit dem letzten Abgleich mit der DB (also seit letztem Speichern oder Laden) gemacht wurden, in einem Rutsch zurückgeschrieben werden - nicht jeder poplige Textbox-Text einzeln.

    guck dirmal die Spielereien auf DBExtensions an - es sind auch einige DetailViews darunter.

    sowas etwa:

    VB.NET-Quellcode

    1. DebitorRow.Debitor_Name1 = Debitor_Name1TextBox.Text
    geht schoma garnicht - das würde man sich alles im FormDesigner generieren lassen, und das würde per Databinding gehen, also das sind so Standard-Tasks, mit denen du als Progger dich so im Einzelnen nicht verkünsteln solltest.

    guggemol "DetailView" auf Movie-Tuts
    Vielen Dank für die rasche Antwort!

    ErfinderDesRades schrieb:

    Nämlich, dass alle Änderungen, die seit dem letzten Abgleich mit der DB (also seit letztem Speichern oder Laden) gemacht wurden, in einem Rutsch zurückgeschrieben werden - nicht jeder poplige Textbox-Text einzeln.
    Okay, das leuchtet mir ein! Aber wie müsste der Code für den "Speichern-Button" denn aussehen, damit alle Änderungen gespeichert werden?

    Ich habe

    VB.NET-Quellcode

    1. Me.TblDebitorenTableAdapter.Update(Me._DatenbankDataSet.tblDebitoren)
    probiert, nur das funktioniert auch nur, wenn ich im DGV nach den Änderungen in den Textboxen einen anderen Datensatz auswähle und dann "Speichern" klicke.

    Ich will aber erreichen, dass ich gleich auf Speichern klicken kann, nachdem die Textboxen im Detailbereich geändert wurden. Quasi ohne dass man vorher noch den Datensatz in der DGV verlassen muss.

    Zeus_EA schrieb:

    das funktioniert auch nur, wenn ich im DGV nach den Änderungen in den Textboxen einen anderen Datensatz auswähle und dann "Speichern" klicke.

    ADO.Net übernimmt die Daten erst nach Validierung ins Dataset, und ein Datensatz wird validiert, erst wenn der nächste aufgesucht wird.
    Du kannst die Validierung auch erzwingen, indem du BindingSource.EndEdit aufrufst.
    Vielen Dank! Das Erzwingen der Validierung war genau das, was gefehlt hat!
    Für alle die zukünftig auch solch einen Button benötigen hier den Code, welcher auch funktioniert.

    VB.NET-Quellcode

    1. Private Sub cmdSpeichern_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSpeichern.Click
    2. Me.TblDebitorenBindingSource.EndEdit()
    3. Me.TblDebitorenTableAdapter.Update(Me._DatenbankDataSet.tblDebitoren)
    4. End Sub


    Vielen Dank an ErfinderdesRades für die schnelle Hilfe und die interesanten Links aus deinem ersten Post!
    Kannst du mir vielleicht noch verraten, wie der Code für den Button "cmdNeu" aussehen müsste?
    Also wenn man diesen Button klickt, müsste ja dann ein neuer, leerer Datensatz angelegt werden und die Textboxen müssten auch leer sein.
    Nach dem Ausfüllen der Textfelder möchte ich dann oben besprochenen "Speichern-Button" drücken, damit der Datensatz in die Datenbank geschrieben wird...

    Vielen Dank bereits im Vorraus!
    in den Samples zu DBExtensions sind doch an verschiedenen Stellen Add-Buttons oder Menüs eingebaut - such da mal bischen rum.

    Oder im Minikass-Sample von DataExpressions - das hat auch ein AddBon - MenuItem.

    Ich verwende sowas eher selten, weil ich neue Datensätze auch gerne anlege, indem ich die Werte direkt in die ZufügeZeile des DGVs reinschreibe.

    Also fast alle meine Samples unterstützen das Zufügen von Datensätzen, nur für Add-Buttons musste'n bischen suchen.
    Es gibt dafür die wunderschöne Methode XYDAtaset.Dingsbumstable.Rows.Add(deineNewDingsbumsTableRow).
    Ich habe des schonma folgendermaßen getätigt:
    Dialogaufruf im Using-Block
    Dem Dialog ne Property DingsBumsRow verpasst un diese mit den Textboxen verfüllt.
    Nach dem Schlißen des Dialogs ...Rows.Add(...)
    feddich

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    @ErfinderDesRades: Danke erst einmal für die Hinweise. Leider muss ich jedoch feststellen, dass die Extensions mich mich als blutiger Anfänger zu komplex zu seien scheinen... nachdem ich nun zwei Tage versucht habe es zu verstehen.

    @Vatter: Kannst du mir deinen Lösungsvorschlag evtl. ein weniger ausführlich beschreiben?

    Vielen Dank euch beiden!
    Also wenn das hier zu kompliziert ist, dann weiß ich auch nicht

    VB.NET-Quellcode

    1. Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
    2. Handles ReloadToolStripMenuItem.Click, SaveToolStripMenuItem.Click, RunArtikelFormToolStripMenuItem.Click, TestToolStripMenuItem.Click, btAddProduct.Click, btCancelEdit.Click, btDelete.Click
    3. Select Case True
    4. Case sender Is ReloadToolStripMenuItem : NorthWindDts.Fill()
    5. Case sender Is SaveToolStripMenuItem : NorthWindDts.Save(Me)
    6. Case sender Is RunArtikelFormToolStripMenuItem
    7. Using frm = New frmArtikels
    8. frm.ShowDialog(Me)
    9. End Using
    10. Case sender Is TestToolStripMenuItem
    11. KundenDataGridView.FirstDisplayedCell = KundenDataGridView(0, 3)
    12. 'srcKategorieArtikel.Position = 2
    13. 'colArtikelID.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
    14. 'srcKategorieArtikel.MoveTo(srcKategorieArtikel.At(2))
    15. 'CheckChanges(NorthWindDts)
    16. Case sender Is btAddProduct
    17. With srcKategorieArtikel.AddNewX(Of ArtikelRow)()
    18. .LieferantenID = 1
    19. End With
    20. Case sender Is btCancelEdit : srcKategorieArtikel.CancelEdit()
    21. Case sender Is btDelete : srcKategorieArtikel.RemoveCurrent()
    22. End Select
    23. End Sub
    kannstes auch fokussieren auf genau den Add-Button

    VB.NET-Quellcode

    1. Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
    2. Handles btAddProduct.Click
    3. Select Case True
    4. Case sender Is btAddProduct
    5. With srcKategorieArtikel.AddNewX(Of ArtikelRow)()
    6. .LieferantenID = 1
    7. End With
    8. End Select
    9. End Sub

    Und noch weiter zusammenstreichen, denn du hast ja keine LieferantenID

    VB.NET-Quellcode

    1. Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
    2. Handles btAddProduct.Click
    3. srcKategorieArtikel.AddNew
    4. End Sub
    Oh man... da hab ich wohl den Wald vor Bäumen nicht mehr gesehen. :pinch: :pinch: :pinch:

    Ich hatte ja den Fokus ja schon auf den "Button-Code" gerichtet, aber ich war durch "srcKategorieArtikel" irgendwie irritiert.
    ... aber nun hab ich's begriffen!!! :thumbsup:

    Vielen Dank nochmal!