Harlequin: .NET: DataView und OnListChanged

Yerf!

Ich hoff mal, das sich auch ein paar .Net-Kenner hier rumtreiben... ich hab da nämlich so ein Problem...

Ich habe eine Klasse die sich von DataView ableitet und das OnListChenged überschreibt:

  
        protected override void OnListChanged(System.ComponentModel.ListChangedEventArgs e)  
        {  
            if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemChanged && e.NewIndex >= 0)  
            {  
                this[e.NewIndex]["Changed"] = DateTime.Now;  
            }  
            base.OnListChanged(e);  
        }  

Das Problem ist: die Änderung innerhalb des Handlers feuert wieder das Event, was zu einer Endlos-Rekursion führt. Leider ist e.PropertyDescriptor null, ansonsten könnte ich abfragen auf welchem Feld die Änderung erfolgte und das "Changed"-Feld davon ausnehmen.

Google hat erst mal auch nicht weiter geholfen. Das einzige was ich gefunden habe ist, dass der PropertyDescriptor nicht null sein sollte, wenn man .NET 4 benutzt (soll ein Bug im 3.5er sein)... ich habs nochmal kontrolliert, das Projekt steht auf .NET4 Client Profile.

Hat noch jemand eine schlaue Idee, kann ich z.B. in einer abgeleiteten Klasse den DataView ändern ohne dass der Event feuert?

Gruß,

Harlequin

--
RIP --- XHTML 2
nur die Besten sterben jung
  1. Hi!

    Das Problem ist: die Änderung innerhalb des Handlers feuert wieder das Event, was zu einer Endlos-Rekursion führt.

    Ich mach mir das in solchen Fällen immer sehr einfach, indem ich ein privates Feld vom Typ bool erstellen, das auf false steht. Im Event-Handler befrage ich dieses und verlasse ihn bei true. Danach kommt try foo = true; ... finally foo = false; Das try-Konstrukt kannst du vielleicht auch weglassen, denn im Falle einer Exception hat man sicher andere Probleme als den Eventhandler wieder zuzulassen.

    Lo!

    1. Yerf!

      Danke, klappt super. Ich hatte schon überlegt den Handler vorübergehend abzukoppeln, aber so ists natürlich einfacher.

      Gruß,

      Harlequin

      --
      RIP --- XHTML 2
      nur die Besten sterben jung
  2. Yerf!

    dieses .NET ist manchmal zum Haare raufen...

    Nächstes Problem: ich will bei einer DataTable das Löschen einer Zeile verhindern. Ich versuchs mit dem RowDeleting-Event, aber ein rejectChanges() wirkt nicht wie geünscht, die Zeile wird trotzdem gelöscht.

      
            data.RowDeleted += new DataRowChangeEventHandler(ListRowDeleting);  
      
    ...  
      
            protected override void ListRowDeleting(object sender, DataRowChangeEventArgs e)  
            {  
                e.Row.RejectChanges();  
                e.Row["Deleted"] = true;  
             }  
    
    

    Im Netz findet man alle möglichen Posts mit Leuten die auch das Problem haben aber irgendwie keine Lösung... gibt es da tatsächlich nichts "sauberes" über einen EventHandler?

    Gruß,

    Harlequin

    --
    RIP --- XHTML 2
    nur die Besten sterben jung
    1. Hi!

      ich will bei einer DataTable das Löschen einer Zeile verhindern. Ich versuchs mit dem RowDeleting-Event, aber ein rejectChanges() wirkt nicht wie geünscht, die Zeile wird trotzdem gelöscht.

      Das Markieren zum Löschen findet ja auch erst zwischen den Ereignissen Deleting und Deleted statt. Ein Zurückweise der Änderungen _vor_ dem Löschmarkierprozess bringt also nichts.

      data.RowDeleted += new DataRowChangeEventHandler(ListRowDeleting);

      Bist du sicher, dass du data.RowDeleted verwendet hast, oben sprichst du schließlich von RowDeleting. Wenn ja, solltest du auch den Namen der Eventhandler-Methode korrigieren. AcceptChanges() hat auch keiner zu früh aufgerufen?

      Zu guter Letzt bleibt immer noch, die Delete-Funktionalität im BindingNavigator (wenn du einen nimmst) zu entfernen und einen eigenen Button hinzuzufügen, den du mit Löschen beschriftest, der dann aber das tut, was du willst.

      Lo!

      1. Yerf!

        Das Markieren zum Löschen findet ja auch erst zwischen den Ereignissen Deleting und Deleted statt. Ein Zurückweise der Änderungen _vor_ dem Löschmarkierprozess bringt also nichts.

        Ah, deswegen ist der RowState im Deleting-Handler "added"... hab mich schon gewundert.

        data.RowDeleted += new DataRowChangeEventHandler(ListRowDeleting);

        Bist du sicher, dass du data.RowDeleted verwendet hast, oben sprichst du schließlich von RowDeleting. Wenn ja, solltest du auch den Namen der Eventhandler-Methode korrigieren. AcceptChanges() hat auch keiner zu früh aufgerufen?

        Oh, das stammt vom rumprobieren, anfangs hatte ich den RowDeleting genommen. AcceptChanges wird zumindest von meinem Code nicht aufgerufen (Fremdcode außer dem Framework selber ist nicht im Spiel). Einzig im RowChanged Event komm ich noch vorbei, aber da hab ich irgendwie auch keine Handhabe.

        Zu guter Letzt bleibt immer noch, die Delete-Funktionalität im BindingNavigator (wenn du einen nimmst) zu entfernen und einen eigenen Button hinzuzufügen, den du mit Löschen beschriftest, der dann aber das tut, was du willst.

        Eine Löschlogik am DataView vorbei zu implementieren wäre kein Problem, würde die Lösung aber in die GUI verlagern (zumindest teilweise, da man Row.Delete() nicht mehr aufrufen dürfte), wo sie eigentlich nicht hingehört... ich versuch das grad sauber zu trennen.

        Gruß,

        Harlequin

        --
        RIP --- XHTML 2
        nur die Besten sterben jung
        1. Hi!

          Zu guter Letzt bleibt immer noch, die Delete-Funktionalität im BindingNavigator (wenn du einen nimmst) zu entfernen und einen eigenen Button hinzuzufügen, den du mit Löschen beschriftest, der dann aber das tut, was du willst.
          Eine Löschlogik am DataView vorbei zu implementieren wäre kein Problem, würde die Lösung aber in die GUI verlagern (zumindest teilweise, da man Row.Delete() nicht mehr aufrufen dürfte), wo sie eigentlich nicht hingehört... ich versuch das grad sauber zu trennen.

          Stimmt. Aber was anderes als die Ereignisse, um den Prozess zu beeinflussen hast du nicht. Überschreiben kann man die Methode nicht. Und wenn es doch ginge, müsste man überall da eingreifen, wo DataRows erzeugt werden und stattdessen die neue Klasse instantiieren.

          Lo!

          1. Yerf!

            Stimmt. Aber was anderes als die Ereignisse, um den Prozess zu beeinflussen hast du nicht. Überschreiben kann man die Methode nicht. Und wenn es doch ginge, müsste man überall da eingreifen, wo DataRows erzeugt werden und stattdessen die neue Klasse instantiieren.

            Eine eigene Implementierung einer DataTable wollt ich meinem DataView dann doch nicht unterjubeln...

            Aber ich hab grad die Lösung gefunden:

            Ich muss den RejectChanges() im Deleted-Event machen. Da hat er zwar erst auch nicht funktioniert, allerdings: ich hab doch vorhin erwähnt, dass der Rowstate im Deleting auf "added" stand... klar, weil ich nach dem Hinzufügen noch keinen AcceptChanges gemacht hab. Der Reject verwirft also auch den Add und die Zeile ist trotzdem weg... nachdem ich den Add jetzt Accepte funktioniert auch das Rejecten vom Delete.

            Gruß,

            Harlequin

            --
            RIP --- XHTML 2
            nur die Besten sterben jung