Combobox im Datagridview Fehler nach Auswahl

  • VB.NET
  • .NET 4.5

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Combobox im Datagridview Fehler nach Auswahl

    Hallo,

    ich habe eine Combobox in einem Datagridview. Die zeigt schlicht Standortkürzel (MEKurz) aus einer Tabelle Standort an. Mit der Combobox kann man im Datagridview einem Datensatz ein Standortkürzel zuweisen.
    Funktioniert alles wunderbar, außer, wenn ich mit der Combobox einen Wert im ersten (!) Datensatz auswähle, bekomme ich eine Exception, dass Spalte MEkurz nicht zu der Tabelle Standort gehört. Die Fehlermeldung klicke ich weg, drücke Escape, um die Änderung zu widerrufen und dann läuft das Programm weiter.
    Wie gesagt, in allen Datensätzen funktioniert das, nur nicht im ersten.



    Viele Grüße,
    Oliver
    Tja, wenn ich nur wüsste, wonach ich da suchen soll. Es knallt ja nur beim ersten Datensatz in der Liste. Ah warte, mir kommt da eine Idee ...
    Ich habe das DGV nun zunächst mal nach der ersten Spalte (Komm Nr) sortiert (drei Mal in den Header geklickt). Jetzt geht eine Zuweisung über die Combobox für alle Zeilen.
    Aber da hätten wir auch schon das nächste Problem.
    Wenn ich das Formular schließe, wird das DataSet automatisch in eine XML Datei gespeichert. Wenn ich es dann wieder öffne, wird es nur unvollständig angezeigt. Fahre ich mit der Maus über die ButtonColumns (Ja, Nein, ...), erscheinen die nach und nach.



    Irgendwann kommt es dann zum "Absturz", im Studio steht
    "Die Anwendung befindet sich im Haltemodus
    Ihre App wurde angehalten, aber es gibt keinen anzuzeigenden Code, da alle Threads externen Code ausgeführt haben (normalerweise System- oder Frameworkcode)."

    Dann kann ich den Debugger nur noch beenden :(

    Ich lege die ein Backup der Solution mal in den Anhang, mit einer DS02-Beipieldatei.
    Dateien
    • ICaSE03.zip

      (525,17 kB, 57 mal heruntergeladen, zuletzt: )
    @OliverSte: Beschreib mal bitte den Weg zum Fehler Schritt für Schritt. Denn ich kann ihn gar nicht reproduzieren, weil ich nicht weiß, wo ich suchen soll.

    Ich starte das Programm, klicke auf [Intervall-CA DS02 Import], [Arbeitsliste kurz], wodurch ein neues Formular angezeigt wird*; dann ändere in der 1. Zeile Daten bei |Teilnehmerin|, |Geb.Datum|, |Scr.Fallnr|, |Screening|, |Mon|, |ICaTyp|
    Was [ja], {nein], [Parken] bedeuten (v.a. sind diese in jeder Tabellenzeile und dann nochmal unten als Extrabuttons) versteh ich zwar nicht, muss ich aber (hoffentlich) auch nicht. Das Problem da ist nur, dass bei [nein] das Programm abstürzt.
    Nur in der Spalte |ME| wird in der ComboBox gar nix gezeigt. Und wenn ich das Form verlassen will, werd ich zwar gefragt, ob gespeichert werden soll, aber gespeichert wird da nix, zumindest nicht über das Programmende hinaus. Ah, ok. Man muss es im Hauptform nochmal explizit über [ICa speichern] sichern und nach Programmstart neu per [ICa laden] zurückholen. Wo jetzt allerdings der Unterschied zwischen [Intervall-CA DS02 Import] und [ICa laden] liegt, hab ich noch nicht raus. Ich weiß nur, dass es zum Problem wird, wenn ich versuche, die über [ICa speichern] gesicherte Datei über [Intervall-CA DS02 Import] aufzurufen.

    *btw: es wird nicht modal, also per ShowDialog angezeigt => ich kann problemlos, während das 2. Form angezeigt wird, nochmal über das erste einen Datenimport machen
    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.
    @ErfinderDesRades ich habe auf 4.5 umgestellt. Hier anbei.
    @VaporiZed Ja, das Programm steht noch ganz am Anfang und da fehlt vorweg ein bisschen was.
    Es läuft gerade so. Aus dem Startformular DS02 importieren, die ICaSE\DS02_N010000_TEST.xml.
    Beim Importieren wird die DS02, welche in das DataSetDS02 geladen wird, in ICaDataSet kopiert. Aber nur das, was da noch nicht drin ist.
    Man kann sich das Ergebnis im Formular "DataSets Betrachten" ansehen. "Mit Beziehungen" funktioniert da nur im Reiter DS02!

    Die Buttons Laden und Speichern im Startformular machen das nur auf dem ICaDataSet!
    Beim Beenden des Arbeitsliste_kurz wird automatisch das ICaDataSet gespeichert. die Datenbankanbindung mache ich, wenn das Programm komplett fertig ist (DataSet only first).

    Damit der Fehler mit den Standorten auftritt, müssen im Startformular einfach mal zwei oder mehr eingegeben werden!

    Alles klar? Wir können uns das auch mal gemeinsam mit TeamViewer ansehen ;) Nur nicht mehr heute, ich bin bei den Nachbarn auf einem Geburtstag :)
    Danke für Eure Hilfe!

    Viele Grüße,
    Oliver
    Dateien
    • ICaSE04.zip

      (525,26 kB, 44 mal heruntergeladen, zuletzt: )
    Bewertungen von Codezeilen wie

    VB.NET-Quellcode

    1. For Each DS02_ivcaRow In DS02Row.GetChildRows("DS02_DS02_ivca")
    2. metadataRow.RZ = DataSetDS02.Tables("DS02_data").Rows(0)("RZ")

    überlassen ich @ErfinderDesRades, der da bestimmt gern was zum Thema typisiertes DataSet zu verlinken und erzählen hat.

    Aber wie Du meinem Screenshot entnehmen kannst, ist da auch nach Ausfüllen aller Zeilen nix von dem beschriebenen Fehler zu finden. Die Combobox in Spalte 2 bleibt aber weiter leer.
    Bilder
    • fehlerfrei.png

      17,34 kB, 971×233, 134 mal angesehen
    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.
    @VaporiZed
    Der Fehler tritt auf, wenn man mit der Combobox einen Wert im ersten Datensatz setzen möchte. Aber auch nur, wenn man das DGV nicht vorher irgendwie sortiert hat.
    Damit überhaupt Daten in der Combobox angezeigt werden, muss Tabelle Standort im ICaDataSet gefüllt werden. Das geht mit dem DGV im Startformular

    Möchtest du mir helfen oder meine Frage ad absurdum führen? Irgendwie bin ich mir da gerade unsicher.

    Viele Grüße,
    Oliver
    Deine

    OliverSte schrieb:

    Frage ad absurdum führen?
    Ich wüsste nicht, wie ich das getan hätte. Aber endlich habe ich die Antwort für meine Bitte aus Post#5:

    VaporiZed schrieb:

    Beschreib mal bitte den Weg zum Fehler Schritt für Schritt.


    Ok, wenn man das DGV auf die Startform zieht, funktioniert es - wie es aussieht - problemlos. Tja, dann kann nur ErfinderDesRades weiterhelfen, da Du seine Umstöpselungsfunktionen verwendest und diese dann wohl letztenendes zu dem Fehler führen. Ich vermute, dass die Änderung der BindingSources das Problem sind, aber das ist ein purer Spekulatius.
    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.
    Guck, ich hab die DbExtensions einfach rausgeworfen, nu gehts immerhin an.
    mit einiger Mühe kann ich nu auch den Fehler reproduzieren.
    Ich weiss aber nicht recht, wie nun weiter machen.
    Als erstes und wichtigstes schreit mich natürlich an, dass Option strict off ist.
    Dann natürlich was VaporiZed sagt: Dass durchgängig untypisiert gegen typisierte Datasetse programmiert ist.



    Aber nach beidem hast du nicht gefragt.
    Worans liegt fund ich nicht raus, aber so tritts nicht mehr auf:
    Das hier weg:

    VB.NET-Quellcode

    1. Private Sub Arbeitsliste_kurz_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. ' auch hier, umbiegen der BindingSource zur Laufzeit
    3. ICaBindingSource.DataSource = Start.ICaDataSet
    4. ICaBindingSource.DataMember = "ICa"
    5. StandortBindingSource.DataSource = Start.ICaDataSet
    6. StandortBindingSource.DataMember = "Standort"
    7. End Sub
    stattdessen in beide Forms:

    VB.NET-Quellcode

    1. Public Sub New()
    2. InitializeComponent()
    3. ICaDataSet.Register(Me, False)
    4. End Sub

    ErfinderDesRades schrieb:

    Als erstes und wichtigstes schreit mich natürlich an, dass Option strict off ist.


    Ich bitte um Entschuldigung, sollte keine Provokation sein. Hab das schon mitbekommen, dass dadurch viele Fehler vermieden werden können. Ich habe einfach nur gedacht, bisher brauche ich darauf nicht zu achten, weil das, was ich da mache, wenig kompliziert ist.
    Hab ich mich getäuscht, denn mit der Option kann ich den Inhalt meiner BindingSource nicht mehr ändern.

    VB.NET-Quellcode

    1. ​ICaBindingSource.Current("ICaTyp") = "Abbruch"

    Muss ich wohl im DataSet machen, aber wie?

    VB.NET-Quellcode

    1. Imports ICaSE.ICaDataSet ' in erste Zeile der Datei
    2. '...
    3. dim rwIca = ICaBindingSource.At(Of IcaRow) ' nun hast du die typisierte IcaRow
    4. rwIca.IcaType = "Abbruch" 'und kannst dieses und vieles andere damit machen
    Aber sone punktuelle auskunft kann dir nicht ersparen, die tuts durchzuarbeiten, verstehen und zu beherzigen.
    Die Sources downloaden und einbinden ist schoma gut, und eröffnet diese Lösung für diese Frage, und hat auch das mit der Registrierung vorhin eröffnet, aber...
    @ErfinderDesRades
    Ich gebe dir völlig Recht, aber bekenne mich nicht in allen Punkten schuldig.
    Ich habe die Tuts gesehen, alle 11 Videos und einiges nachgebaut. Ich habe sogar ein klitzekleines Beispiel programmiert, damit ich hier konkret fragen kann, um dann festzustellen, dass es abgesehen von den Bezeichnungen nahezu 1:1 deinem im englischen Tut "Relationale Datenbanken" entspricht.

    Das Problem ist und danach fragte ich dich schon mal in privater Kommunikation, dass unklar ist, wann man deine Extensions benutzt, und welche es gibt. Und beim Klickiklicki mit dem Designer erschließt sich das auch nicht.
    Ich habe daraufhin deine Sourcen durchgelesen und bin nicht schlauer geworden. Hab ich vielleicht zu schnell oder oberflächlich durchflogen.

    Jedenfalls habe ich einfach mal angefangen und frage konkrete Probleme ab. Wie soll ich sonst voran kommen?

    Btw, wieso programmiere ich durchgehend untypisiert? Was genau ist damit gemeint? Der Kompiler zwingt mich doch zu korrektem Code.

    Allein das Registrieren des Datasets für die Form oder umgekehrt. Woher hätte ich das wissen müssen? Natürlich steht das in deinen Beispielcodes, aber nicht, dass man das selbst dort einfügen muss. Oder habe ich da was übersehen? Ich war voll stolz auf mich, die Idee gehabt zu haben, die Datasource der Bindingsource umzubiegen. Und jetzt wird mir gesagt, dass das leider Mist war.

    Erstmal herzlichen Dank für die Hilfe. Ich will mal schauen, ob ich in den Tuts etwas übersehen habe.

    Viele Grüße,
    Oliver

    OliverSte schrieb:

    Ich war voll stolz auf mich, die Idee gehabt zu haben, die Datasource der Bindingsource umzubiegen. Und jetzt wird mir gesagt, dass das leider Mist war.
    Nee - so meine ich das nicht.
    Wenn du da selbst drauf gekommen bist, ist das eine Super-Leistung.
    Weil das ist genau dieselbe GrundIdee, die ich dann mit meine register-Erfindung auf die Spitze getrieben hab.
    Also du hast das Rad neu erfunden, und solch ist immer zunächstmal eine ausgezeichnete kreative Leistung.
    Dasses das schon gibt, ist einerseits ein Wehrmutstropfen, andererseits aber auch schlagender Beweis dafür, dass die Erfindung gut und sinnvoll ist - sonst hätte sie sich ja nicht bereits etabliert haben können.



    Zum Unterschied typisiert/untypisiert probier einfach post#14 aus. Da stellst du fest, bei typisiertem Programmieren sagt dir Intellisense viel mehr vor.
    auch kannst du dir im ObjectBrowser mal die IcaRow angucken, das ergibt alles iwie einen Sinn, was diese Klasse bereitstellt.
    Bei untypisierter Programmierung:

    OliverSte schrieb:

    VB.NET-Quellcode

    1. ICaBindingSource.Current("ICaTyp") = "Abbruch"
    weisst du nichtmal, dasses eine Klasse IcaRow überhaupt gibt - ja, das ist wohl der wesentliche Unterschied.



    Ja, das mitte Dokumentation ist problematisch.
    Eiglich kann man ja im ObjectBrowser jede Methode/Property/etc. auffinden.
    Und Intellisense sollte auch alles verfügbare anbieten.
    Aber bei Extension-Methods leider nicht (jdfs. nicht bis 2013, ich hoffe, sie werden das mal nachrüsten).

    Tja, ich kenne meine Extensions, aber ich hab leider noch kein gutes System gefunden, wie man systematisch dokumentieren könnte, wasses alles gibt.

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

    @ErfinderDesRades
    Naja, ich weiß es ganz genau, also was der ObjektBrowser so alles hergibt, aber nicht, wann was benutzt werden muss.

    Guck mal, in dem hier zitierten CellClick Ereignis (Klick auf einen der Ja, Nein, Abbruch Buttons in den ButtonColumns) benutzte ich bereits:

    VB.NET-Quellcode

    1. Dim rowICa As ICaDataSet.ICaRow = DirectCast(DirectCast(ICaBindingSource.Current, DataRowView).Row, ICaDataSet.ICaRow)

    zum Auslesen der angeklickten Zeile. Da hab ich ja schon mein Row-Objekt. Ich wusste nur nicht, dass eine Änderung desselben diese Änderung ins DataSet zurückschreibt. Oder macht es das auch gar nicht?
    Muss man dann noch ein rowICa.EndEdit() abschicken und zu guter Letzt ein DGV.refresh?
    nö - dassis eiglich perfekt. Und das ist der Datensatz im Dataset, wennde den änderst, isser halt geändert.
    Und musst auch nix hinterherschicken zum iwas anzeigen - Databinding macht das.
    paar Vereinfachungen:

    VB.NET-Quellcode

    1. Dim rowICa = DirectCast(DirectCast(ICaBindingSource.Current, DataRowView).Row, ICaDataSet.ICaRow)
    option infer on weiss bereits den Datentyp - brauchste nicht extra hinschreiben.
    Und um den hässlichen DoppelCast zu vermeiden habich dafür auch ein Extension:

    VB.NET-Quellcode

    1. Dim rowICa = ICaBindingSource.At(of ICaRow)