Announcement

Collapse
No announcement yet.

RowState im DataSet

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • RowState im DataSet

    Hallo Andreas und alle zusammen,

    ich habe ein kleines Problem mit dem Status des aktuellen Satzes im DataSet.
    Ich habe ein Panel in einer Form, auf dem sich einige TextBoxen befinden, in denen Werte verändert werden können. Dahinter liegt ein DataSet, welches wiederum aus einer Access-DB geladen wird.
    Wenn ich die TextBox editiert habe, möchte ich über einen Button das Speichern in die Access-DB auslösen.
    Dazu ermittle ich mir ein DataSet mit den geänderten Rows mit Hilfe der GetChanges-Methode.
    Leider hat der aktuelle Satz des Panels, egal was ich auch mache, wieviel ich auch ändere, immer noch den Status "Unchanged", obwohl ich mir über den Debugger und auch über MessageBoxen den Inhalt des Records aus dem DataSet anzeigen ließ, und der hat den neuen Inhalt, aber "Unchanged"! Damit zieht dann auch die Update-Methode nicht.
    Wenn ich in ein anderes Panel wechsele, ist der Status des Records immer noch "Unchanged". Erst wenn ich wieder zurück in das Panel wechsle, wo ich geändert habe, wandelt sich endlich der Status in "Modified".
    Die Datenbindung läuft über das normale BindingContext.
    Was muß ich machen, damit der aktuelle Satz des DataSets, wenn ich im Panel ändere, den Status "Modified" bekommt?
    Gibt es irgendeinen schlauen EventHandler oder eine Methode, die sozusagen den Modified-Status erzeugt? Oder was habe ich vergessen? Oder muß ich tatsächlich den Modified-Status selbst organisieren?

    Vielen Dank für Eure Hilfe.
    Grüße von Rolf

  • #2
    Hallo,

    immer dann, wenn Controls über den <i>CurrencyManager</i> an ein DataSet gebunden werden, kontrolliert der CurrencyManager den Zeitpunkt der Aktualisierung des DataSets. ADO.NET geht davon aus, dass der Inhalt des DataSets nur zu 2 Zeitpunkten aktualisiert wird:<br>
    a) CurrencyManager ändert seine Position (d.h. wechselt zu einem anderen Datensatz)<br>
    b) Programm ruft die CurrencyManager-Methode <b>EndCurrentEdit</b> auf

    Wenn man sich das vom Datenbankformular-Experten von VS.NET generierte Beispiel anschaut, fällt auf, dass Microsoft dort vor jedem Update-Aufruf zur Sicherheit EndCurrentEdit aufruft. Das könnte so aussehen:
    <pre>
    aCurrencyManager.EndCurrentEdit()
    SqlDataAdapter1.Update(Me.DataSet11, "DataTableName")
    </pre>
    P.S: Man muss aufpassen, den "richtigen" CurrencyManager zu erwischen, der tatsächlich für dieses Control zuständig ist

    Comment


    • #3
      Hallo Andreas,
      vielen Dank für die Antwort, ich bin erst mal ein Stück weitergekommen, aber leider nur eine Stück.
      Ich habe - vereinfacht dargestellt - 3 Forms mit jeweils einem Panel, auf dem sich editierbare Textboxen befinden.
      Zu jeder Form und damit zu jedem Panel gehört eine Tabelle des DataSets.
      Jedes Panel ist über ein BindingContext mit einer Tabelle des DataSets verbunden.
      Ich habe einen Tree mit Nodes, über die ich die Panels aufrufe.
      Die Panels überlagern sich, d.h. es wird immer nur das aktuelle angezeigt.
      Der "Save"-Button, der erst mal das Abspeichern erledigen soll, befindet sich auf dem Main-Panel, in das jeweils das aktuelle Panel hineingeladen wird.
      Wenn ich mich in ein Panel bewege, dort editiere und meinen "Save"-Button betätige, durchlaufe ich eine Methode, die für alle 3 Panels die BindingContext[...].EndCurrentEdit()-Methode aufruft.
      Wenn ich nur in einem Panel editiere und danach (vor dem Wechsel in ein anderes) den "Save"-Button betätige, klappt alles. Aber sobald ich im ersten Panel editiere, ohne zu speichern in das zweite wechsele und dort editiere und erst dann den "Save"-Button betätige, passiert gar nichts. Alle geänderten Werte sind schon im DataSet "angekommen", aber sämtliche EndCurrentEdits() bewirken nichts. Nur wenn ich folgendermaßen vorgehe:
      Panel 1 editieren, Panel 2 editieren, wieder in Panel 1 zurückclicken, dann "Save" betätigen - erst dann wird die Änderung akzeptiert (und zwar für alle geänderten Textfelder, von beiden Panels).
      Wie gesagt, ich habe nur 3 Panels mit 3 BindingContexts, ich weiß nicht, wo ich den Fehler mache. Ich rufe die Methode EndCurrentEdit() folgendermaßen auf:
      BindingContext[DataSet.Tabelle1].Position = CurrentPosition;
      BindingContext[DataSet.Tabelle1].EndCurrentEdit();
      - ist das evtl. hier falsch? Ich habe aber auch schon das Setzen der CurrentPosition weggelassen oder auch alle vorhandenen Positionen durchlaufen - keine Chance! Wie bekomme ich den aktuellen Currency-Manager zu fassen?
      Gibt es ein Event, das immer beim Verlassen eines Panels zieht und in dem man dann immer das EndCurrentEdit() aufrufen kann?

      Vielen Dank für Eure Hilfe Rol

      Comment


      • #4
        Hallo,

        die extreme Flexiblität des Data Binding von .NET sorgt als Nebenwirkung dafür, dass man sehr schnell auf Irrwege gerät. Ich würde daher den Verweis auf den CurrencyManager explizit anfordern, um sicher zu gehen, immer den "richtigen" zu erwischen. Das könnte etwa so aussehen:
        <pre>
        /*
        * Tabellen Orders und Order Details aus der Northwind-Beispieldatenbank
        * in ein DataSet laden. 2 DataGrid mit je einer Tabelle verbinden.
        * Keine Beziehungen zwischen beiden Tabellen im XML Schema Designer
        * konfigurieren - die Synchroniation soll statt dessen direkt über
        * eine Kopplung im Sourcecode erfolgen.
        */

        private CurrencyManager aCM;

        private void Grid1PosChanged(object sender, System.EventArgs e)
        {
        Trace.WriteLine("Grid1PosChanged");
        // OrderDetails-DataGrid mit einem DataView verbinden
        DataRowView aDRV = (DataRowView)aCM.Current;
        DataView aDV = aDRV.CreateChildView("OrderOrderDetails");
        dataGrid2.DataSource = aDV;
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
        sqlDataAdapterORDERS.Fill(dataSetNorthwind1, "Orders");
        sqlDataAdapterORDERDETAILS.Fill(dataSetNorthwind1, "Order Details");
        // Beziehung zwischen beiden Datenmengen deklarieren
        DataRelation aDR = dataSetNorthwind1.Relations.Add("OrderOrderDetails ",
        dataSetNorthwind1.Tables["Orders"].Columns["OrderID"],
        dataSetNorthwind1.Tables["Order Details"].Columns["OrderID"]);
        // Orders-DataGrid mit der Datenmenge Orders verbinden
        dataGrid1.DataSource = dataSetNorthwind1;
        dataGrid1.DataMember = "Orders";
        aCM = (CurrencyManager)BindingContext[dataSetNorthwind1, "Orders"];
        aCM.PositionChanged += new System.EventHandler(Grid1PosChanged);
        }
        </pre>
        Der Verweis über <i>aCM</i> ist jedoch nur dann für die einzelnen Controls gültig, wenn diese beim Binding ebenfalls den gleichen Zugriffspfad auf die Datenquelle verwenden (ansonsten richtet .NET verschiedene CurrencyManager ein)

        Comment

        Working...
        X