Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TObjectList reagiert nicht auf ModifyAction (https://www.delphipraxis.net/161129-tobjectlist-reagiert-nicht-auf-modifyaction.html)

RWarnecke 18. Jun 2011 13:05

Delphi-Version: 2010

TObjectList reagiert nicht auf ModifyAction
 
Hallo zusammen,

ich habe folgendermassen eine Klasse und eine TObjectList deklariert :
Delphi-Quellcode:
  TModifyActionList = (lnNone, lnChange, lnDelete);
  //
  //  Event zur Erstellung eines neuen Datensatzes für die Ansprechpartner
  //
  TAnsprechpartnerListe = class;
  TAnsprechpartnerListeAddEvent = procedure(Sender: TObject; Gesellschafter: TAnsprechpartnerListe) of object;
  //
  // Zur Speicherung der Ansprechpartnerliste
  //
  TAnsprechpartnerListe = class
  private
    FOnChange      : TAnsprechpartnerListeAddEvent;
    FModifyAction  : TModifyActionList;
    FKundenNr      : string;
    FVorname       : string;
    FNachname      : string;
    FTelefon1       : string;
    FTelefon2       : string;
    FFax           : string;
    FMobil         : string;
    FEMail         : string;
    procedure SetKundenNr(Value: string);
    procedure SetVorname(Value: string);
    procedure SetNachname(Value: string);
    procedure SetTelefon1(Value: string);
    procedure SetTelefon2(Value: string);
    procedure SetFax(Value: string);
    procedure SetMobil(Value: string);
    procedure SetEMail(Value: string);
    function GetKundenNr: string;
    function GetVorname: string;
    function GetNachname: string;
    function GetTelefon1: string;
    function GetTelefon2: string;
    function GetFax: string;
    function GetMobil: string;
    function GetEMail: string;
  public
    constructor Create;
    property KundenNr      : string read GetKundenNr write SetKundenNr;
    property Vorname       : string read GetVorname  write SetVorname;
    property Nachname      : string read GetNachname write SetNachname;
    property Telefon1       : string read GetTelefon1  write SetTelefon1;
    property Telefon2       : string read GetTelefon2  write SetTelefon2;
    property Fax           : string read GetFax      write SetFax;
    property Mobil         : string read GetMobil    write SetMobil;
    property EMail         : string read GetEMail    write SetEMail;
    property ModifyAction : TModifyActionList read FModifyAction write FModifyAction;
    property OnChange: TAnsprechpartnerListeAddEvent read FOnChange write FOnChange;
  end;
  //
  //  Erstellen und Speichern der Kundenliste
  //
  TAnsprechpartnerObjListe = class(TObjectList)
  private
    FOnChange    : TAnsprechpartnerListeAddEvent;
    FModifyAction : TModifyActionList;
    FNewRecord   : Boolean;
    procedure DeleteRecord(Klasse: TAnsprechpartnerListe);
  protected
    function getItem(Index: Integer): TAnsprechpartnerListe; virtual;
    procedure setItem(Index: Integer; Objekt: TAnsprechpartnerListe); virtual;
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  public
    function Add(Objekt: TAnsprechpartnerListe): Integer; virtual;
    function NewRecord(Objekt: TAnsprechpartnerListe): Integer; virtual;
    function Remove(Objekt: TAnsprechpartnerListe): Integer; virtual;
    function IndexOf(Objekt: TAnsprechpartnerListe): Integer; virtual;
    procedure Insert(Index: Integer; Objekt: TAnsprechpartnerListe); virtual;
    property Items[index: Integer]: TAnsprechpartnerListe read getItem write setItem; default;
    property ModifyAction : TModifyActionList read FModifyAction write FModifyAction;
    property OnChange: TAnsprechpartnerListeAddEvent read FOnChange write FOnChange;
  end;
In dem Programm wo diese TObjectList eingesetzt wird, wir die ObjectList beim Erstellen des DataModuls miterstellt und die Procedure für das OnChange-Event übergeben.
Delphi-Quellcode:
  AnsprechpartnerListe := TAnsprechpartnerObjListe.Create(True);
  AnsprechpartnerListe.OnChange := AnsprechpartnerListeChange;
Wenn ich jetzt das Property ModifyAction mit dem Wert "lnChange" aufrufe, passiert garnicht. Keine Fehlermeldung oder Hinweis. In einem anderen Programm, welches ich unter 2007 geschrieben habe, funktioniert diese Variante sehr gut. Normal sollte das Setzen von lnChange auf die Eigenschaft ModifyAction die procedure getItem aufrufen,was aber unter Delphi 2010 nicht funktioniert.

Hat jemand eine Idee, wieso es nicht klappt ? Gibt es irgendwelche Unterschiede zwischen Delphi 2007 und Delphi 2010 bei der Benutzung der TObjectList ?

stahli 18. Jun 2011 13:47

AW: TObjectList reagiert nicht auf ModifyAction
 
Ich habe mal versucht, deinen Ausschnitt nachzuvollziehen.

Irgendwo müsstest Du sicher prüfen, ob eine Ereignisbehandlung zugewiesen ist:
Delphi-Quellcode:
if Assigned(OnChange) then
  OnChange(...);
Wird dieser Aufruf erreicht? Ist dies möglicherwise abhängig von einer Zeichnung einer sichtbaren Komponente?
Ich denke, Du müsstest mal etwas mehr zeigen.

sx2008 18. Jun 2011 13:59

AW: TObjectList reagiert nicht auf ModifyAction
 
Also ich sehe da einige Fehler im Design:
1.) Die Klasse TAnsprechpartnerListe muss in Wirklichkeit TAnsprechpartner heissen, denn es handelt sich um keine "Liste"!!
Nur eine Namensänderung aber daraus folgen weitere Dinge
2.) Die Klasse TAnsprechpartner kann im Grunde genommen nur ein OnChange-Event besitzen, denn sie weiss nicht, ob sie irgendwo hinzugefügt oder gelöscht wurde.
Das Property ModifyAction gehört auch nicht in diese Klasse.
Delphi-Quellcode:
TAnsprechpartner = class
protected
  procedure DoChange;
....
public
  property OnChange:TNotifyEvent read FOnChange write FOnChange;
end;

// Events sollte man immer über eine Hilfsprocedure auslösen
procedure TAnsprechpartner.DoChange;
begin
  if Assigned(FOnChange) then
    FOnChange(self);
end;
3.) Die Klasse TAnsprechpartnerObjListe bekommt natürlich mit, wenn ein Objekt hinzugefügt oder gelöscht wird.
Aber sie kann nicht erkennen wenn ein Objekt der Klasse TAnsprechpartner verändert wird.
Es ist dann aber möglich dass TAnsprechpartnerObjListe beim Hinzufügen eine TAnsprechpartner-Objekts das OnChange-Event auf einen interen Eventhandler richtet und so über Änderungen informiert wird.

Uwe Raabe 18. Jun 2011 14:20

AW: TObjectList reagiert nicht auf ModifyAction
 
Zitat:

Zitat von RWarnecke (Beitrag 1107121)
Normal sollte das Setzen von lnChange auf die Eigenschaft ModifyAction die procedure getItem aufrufen,

Wieso? Das Property ModifyAction hat als Setter lediglich das entsprechende Feld FModifyAction angegeben. Ein Schreiben auf das Property kann damit eigentlich gar nichts auslösen (zumindest nicht direkt). Ich behaupte auch mal, daß das unter D2007 nicht anders ist.

Wobei ich mir hier nebenbei die Frage stelle, warum das Setzen des Properties ModifyAction überhaupt getItem aufrufen sollte...

Ansonsten kann ich mich nur stahli anschließen: Ich denke, Du müsstest mal etwas mehr zeigen.

stahli 18. Jun 2011 14:24

AW: TObjectList reagiert nicht auf ModifyAction
 
Es soll vermutlich den Modus umstellen, ähnlich wie bei TTable.Insert ... TTable.Post.
Ich denke auch, dass die Bezeichnungen nicht ganz schlüssig bzw. erst mal (im ersten Moment) etwas irreführend sind.

RWarnecke 18. Jun 2011 14:46

AW: TObjectList reagiert nicht auf ModifyAction
 
Hallo zusammen,

danke erstmal für Eure Antworten. Ich habe den Fehler gefunden. Diese zwei folgenden Zeilen haben in den Set-Proceduren von TAnsprechpartnerListe gefehlt :
Delphi-Quellcode:
  if (Assigned(FOnChange)) and (FModifyAction = lnChange) then
    FOnChange(Self, Self);
Damit funktioniert jetzt alles so wie es soll. Eine vollständige Set-Procedure von TAnsprechpartnerListe sieht dann jetzt so aus :
Delphi-Quellcode:
procedure TAnsprechpartnerListe.SetMobil(Value: string);
begin
  FMobil := Value;
  if (Assigned(FOnChange)) and (FModifyAction = lnChange) then
    FOnChange(Self, Self);
end;
Wenn ich jetzt im Programm auf eine Änderung in einem Eingabefeld reagieren sieht das ganze so aus :
Delphi-Quellcode:
    with TAnsprechpartnerListe(AnsprechpartnerListe.Items[AdvLV_CustomerContacts.Selected.Index]) do
    begin
      ModifyAction := lnChange;
      KundenNr := TKundenListe(KundenListe.Items[MainForm.AdvLV_OverviewList.Selected.Index]).KundenNr;
      Vorname := CustomerContact.AdvEdt_CustomerContactsVorname.Text;
      Nachname := CustomerContact.AdvEdt_CustomerContactsNachname.Text;
      Telefon1 := CustomerContact.AdvEdt_CustomerContactsTelefon1.Text;
      Telefon2 := CustomerContact.AdvEdt_CustomerContactsTelefon2.Text;
      Fax     := CustomerContact.AdvEdt_CustomerContactsFax.Text;
      Mobil   := CustomerContact.AdvEdt_CustomerContactsMobil.Text;
      EMail   := CustomerContact.AdvEdt_CustomerContactsEMail.Text;
      ModifyAction := lnNone;
    end;
Damit werden dann alle Änderungen in die Datenbank geschrieben.

Edit: Rechtschreibfehler korrigiert.

stahli 18. Jun 2011 15:01

AW: TObjectList reagiert nicht auf ModifyAction
 
Mal zwei Nachfragem zum grundsätzlichen Konzept:

Du nutzt eine Datenbank? Warum keine DB-Komponenten?

Dann überträgst Du mehrere ...Edit.Text händisch in zugehörige Objekteigenschaften.
Hast Du Dir schon einmal data binding angesehen, ob das etwas für Dich wäre?
Je nachdem, wie weit Du mit Deinem Projekt bist, könnte Dir so etwas evtl. die weitere Arbeit erleichtern...

RWarnecke 18. Jun 2011 17:25

AW: TObjectList reagiert nicht auf ModifyAction
 
Zitat:

Zitat von stahli (Beitrag 1107158)
Du nutzt eine Datenbank?

Ja,ich nutze eine Firebird-Datenbank.
Zitat:

Zitat von stahli (Beitrag 1107158)
Warum keine DB-Komponenten?

Ich nutze deshalb keine DB-Komponenten, weil ich zum einen mit den Dingern nie richtig zurechtgekommen bin und zweitens habe ich im Moment in meinem Projekt lediglich nur zwei Units, die ich anpacken müsste, wenn denn mal eine andere Datenbank-Komponente zum Einsatz kommen müsste. Zum Beispiel, ich will mein Programm auch noch für ein anderes DBMS zugänglich machen.

Zitat:

Zitat von stahli (Beitrag 1107158)
Dann überträgst Du mehrere ...Edit.Text händisch in zugehörige Objekteigenschaften.
Hast Du Dir schon einmal data binding angesehen, ob das etwas für Dich wäre?
Je nachdem, wie weit Du mit Deinem Projekt bist, könnte Dir so etwas evtl. die weitere Arbeit erleichtern...

Mein Projekt ist noch nicht soweit. Habe bis jetzt lediglich die Kundenverwaltung angefangen.

Stevie 18. Jun 2011 17:48

AW: TObjectList reagiert nicht auf ModifyAction
 
Muss dein Programmcode abwärtskompatibel (< Delphi 2010) sein? Wenn nicht, dann würde ich empfehlen, dich mal mit Generics zu beschäftigen, und die TObjectList<TAnsprechpartner> zu nutzen.

Wenn ich mir den Source Ausschnitt anschaue, entstehen bei mir auch die Fragen, warum in der Datenobjekt Klasse ein Event steht, was in der Liste enthalten sein sollte. Diese sollte nämlich mitbekommen, wenn ein Element hinzukommt, oder rausgenommen wird. Dies ist übrigens auch in sowohl TObjectList, als auch TObjectList<T> enthalten. Für die Benachrichtigung, wenn ein Wert innerhalb des Datenobjekts verändert wurde, solltest du einen anderen Eventtyp implementieren. Solltest du dich für die Databinding Lösung entscheiden, gibt es dort eine entsprechende Basisklasse, die diese Funktionalität implementiert.

Wenn dein Programm noch am Anfang der Entwicklung steht, würde ich dir auch nahelegen, dich mit dem Data Binding Thema zu beschäftigen, denn es klingt gerade zu nach dem prädestinierten Anwendungsgebiet dafür. Falls du Fragen hast und/oder Hilfe brauchst, stehen dir ja einige Wege offen, mich zu erreichen.

RWarnecke 18. Jun 2011 18:05

AW: TObjectList reagiert nicht auf ModifyAction
 
Hallo Stefan,

Zitat:

Zitat von Stevie (Beitrag 1107196)
Muss dein Programmcode abwärtskompatibel (< Delphi 2010) sein?

Nein,mein Programmcode muss nicht abwärtskompatibel sein.
Zitat:

Zitat von Stevie (Beitrag 1107196)
Wenn nicht, dann würde ich empfehlen, dich mal mit Generics zu beschäftigen, und die TObjectList<TAnsprechpartner> zu nutzen.

In wie weit erleichtern die mir die Arbeit ?

Zitat:

Zitat von Stevie (Beitrag 1107196)
Wenn ich mir den Source Ausschnitt anschaue, entstehen bei mir auch die Fragen, warum in der Datenobjekt Klasse ein Event steht, was in der Liste enthalten sein sollte. Diese sollte nämlich mitbekommen, wenn ein Element hinzukommt, oder rausgenommen wird. Dies ist übrigens auch in sowohl TObjectList, als auch TObjectList<T> enthalten. Für die Benachrichtigung, wenn ein Wert innerhalb des Datenobjekts verändert wurde, solltest du einen anderen Eventtyp implementieren. Solltest du dich für die Databinding Lösung entscheiden, gibt es dort eine entsprechende Basisklasse, die diese Funktionalität implementiert.

Ich habe damals nach einer Möglichkeit gesucht, die Datenbank-Abfragen vom eigentlichen Programmcode zu trennen. Da bin ich auf die TObjectList mit einer Klasse gekommen und habe mir dieses Konstrukt zusammengebaut, welches auch recht zuverlässig funktioniert. Ich bin natürlich für neue Ideen offen, die mir das Leben noch erleichtern.

Zitat:

Zitat von Stevie (Beitrag 1107196)
Wenn dein Programm noch am Anfang der Entwicklung steht, würde ich dir auch nahelegen, dich mit dem Data Binding Thema zu beschäftigen, denn es klingt gerade zu nach dem prädestinierten Anwendungsgebiet dafür. Falls du Fragen hast und/oder Hilfe brauchst, stehen dir ja einige Wege offen, mich zu erreichen.

Mein Programm steht noch am Anfang der Entwicklung. Ich habe gerade mal die Kundenverwaltung fertig. Ich schaue mir schon Dein Projekt Data Bindings an. Danke schon mal für Dein Hilfeangebot. Wenn ich irgendwas nicht verstehe, werde ich gerne darauf zurückkommen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:19 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz