Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Bei TList, Record auf Datenänderung reagieren (https://www.delphipraxis.net/145234-bei-tlist-record-auf-datenaenderung-reagieren.html)

RWarnecke 27. Dez 2009 10:07


Bei TList, Record auf Datenänderung reagieren
 
Hallo zusammen,

ich habe diesen Teil des Tutorial durchgelesen und auch gleich umgesetzt. Dabei habe ich folgende Deklaration :
Delphi-Quellcode:
type
  PGesellschaftsname = ^TGesellschaftsname;
  TGesellschaftsname = record
    StammNr           : Integer;
    Gesellschaftername : string;
    Zeichnungskapital : Double;
    ZweiteZahlung     : TDateTime;
    ZahlenderBetrag   : Double;
  end;

var
  Gesellschafter     : PGesellschaftsname;
  GesellschafterListe : TList;
Das funktioniert alles soweit nach dem Tutorial. Nun stelle ich mir die Frage, wie kann ich jetzt auf Änderung in den Daten reagieren um diese Änderung dann in eine Datenbank zu schreiben ?

taaktaak 27. Dez 2009 10:22

Re: Bei TList, Record auf Datenänderung reagieren
 
Moin Moin Rolf,
ich denke, ich habe diese Anforderung auch schon mal gehabt.Hier wurde mir geholfen

RWarnecke 27. Dez 2009 10:29

Re: Bei TList, Record auf Datenänderung reagieren
 
Moin Moin Ralph,

danke erstmal für Deine Antwort. Nur verstehe ich noch nicht ganz wie mir das Beispiel weiterhelfen soll, da ich kein Grid habe, sondern nur verstreute Werte in der Anwendung. Diese verstreuten Werte sind lediglich nur in Editfeldern oder ListViews untergebracht.

thkerkmann 27. Dez 2009 10:35

Re: Bei TList, Record auf Datenänderung reagieren
 
Hi,

wie wär's, wenn Du statt des Records eine Class mit Properties und Gettern und Settern verwendest, und dann ein OnChange Event implementierst ?

Gruss

RWarnecke 27. Dez 2009 10:37

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von thkerkmann
Hi,

wie wär's, wenn Du statt des Records eine Class mit Properties und Gettern und Settern verwendest, und dann ein OnChange Event implementierst ?

Gruss

Hä und wie macht man das ? Hast Du dazu auch ein Tutorial ? Weil ich habe das bis jetzt noch nicht so bewusst gemacht.

Edit: Ok, jetzt weiß ich was Du meinst. Ich habe dabei nur ein Problem, wie verbinde ich eine Klasse mit TList, da ich durch die TList ja auch mehrere Werte speichern kann. Bei einer Klasse kann ich das ja so ohne weitere ja nicht oder ? Und dann kommt das zweite Problem, ich habe noch nie ein OnChange Event geschrieben.

himitsu 27. Dez 2009 10:57

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von thkerkmann
wie wär's, wenn Du statt des Records eine Class mit Properties und Gettern und Settern verwendest, und dann ein OnChange Event implementierst ?

Man benötigt erstmal einen Einstiegspunkt, wo man auf eine Änderung reagieren kann.

Bei Records wird im Allgemeinen nur DIREKT der wert geändert und es gibt keine Möglichkeit über eine Änderung informiert zu werden (außer wenn den Speicherbereich sperrt, wo man sich bei Zugriff eine Systemexception auslösen lassen kann, welche man dann passend behandelt ... ist aber nicht grad optimal).

Alternativ kann man seit Delphi 2006 / TDE auch Records mit Properties versehen und hätte so dann den nötigen Einstiegspunkt, um sowas wie OnChange zu implementieren.

thkerkmann 27. Dez 2009 11:01

Re: Bei TList, Record auf Datenänderung reagieren
 
Hi,

Das geht dann (fast) genauso, wie mit deinem Record. Du erstellst doch mehrere Records (z.B. mit Getmem) und fügst sie der Liste hinzu.
Erstelle stattdessen mehrere Instanzen der Klasse und füge sie der Liste hinzu.

Delphi-Quellcode:
type
  tMyClass = class
  private
    FWert: integer;
    FOnChange: tNotifyEvent;
    procedure SetWert(Value:integer);
    function GetWert:integer;
  public
    property Wert: integer read GetWert write SetWert;
    property OnChange: tNotifyEvent read FOnChange write FOnChange;
  end;


procedure tMyClass.SetWert(Value:integer);
begin
  FWert := Value;
  if Assigned(FonChange) then
    FOnChange(Self);
end;

function tMyClass.GetWert:integer;
begin
  result := FWert;
end;

...

  aClass := tMyClass.Create;
  aClass.OnChange := WertAenderung;
  aList.Add(aClass);
...


procedure tMyForm.WertAenderung(Sender:tObject);
begin
  showmessage('aha es hat sich was geändert');
end;
und wenn es zum Aufräumen kommt, nicht vergessen die Objekte der Liste freizugeben. Nur nicht mit FreeMem, sondern mit Free.

P.S.
Jetzt kommen gleich wieder die Einwände eine TOjectList zu nehmen, weil man das dann der Liste überlassen kann, aber es geht hier um das Verständnis und nicht um die Eleganz. :D

RWarnecke 27. Dez 2009 11:10

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo Thomas,

danke erstmal für Deine ausführliche Antwort. Ich werde mir jetzt mal Dein Beispiel zu gemüte führen und ausprobieren.

Zitat:

Zitat von thkerkmann
... aber es geht hier um das Verständnis und nicht um die Eleganz. :D

Genau darum geht es.

taaktaak 27. Dez 2009 15:06

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo Rolf,
naeher betrachtet geht es in dem Link ja um eine TList, dass Daten fuer ein Grid gespeichert werden ist eigentlich nebensaechlich. Um ueber Aenderungen informiert zu werden, wird fuer TList ein OnChange-Event implementiert. Aber es gibt ja nun schon einige andere Hinweise, die den gleichen / einen aehnlichen Weg aufzeigen.

RWarnecke 27. Dez 2009 16:00

Re: Bei TList, Record auf Datenänderung reagieren
 
Ich habe das ganze jetzt mal umgebaut und ausprobiert nach dem Vorschlag von Thomas. Das mit dem Eintrag der Daten funktioniert so weit. Meine Deklaration sieht jetzt so aus :
Delphi-Quellcode:
type
  TGesellschaftsname = class
  private
    FOnChange          : TNotifyEvent;
    FStammNr           : Integer;
    FGesellschaftername : string;
    FZeichnungskapital : Double;
    FZweiteZahlung     : TDateTime;
    FZahlenderBetrag   : Double;
    procedure SetStammNr(Value: Integer);
    procedure SetGesellschaftername(Value: String);
    procedure SetZeichnungskapital(Value: Double);
    procedure SetZweiteZahlung(Value: TDateTime);
    procedure SetZahlenderBetrag(Value: Double);
    function GetStammNr:Integer;
    function GetGesellschaftername:String;
    function GetZeichnungskapital:Double;
    function GetZweiteZahlung:TDateTime;
    function GetZahlenderBetrag:Double;
  public
    property StammNr           : Integer     read GetStammNr           write SetStammNr;
    property Gesellschaftername : string      read GetGesellschaftername write SetGesellschaftername;
    property Zeichnungskapital : Double      read GetZeichnungskapital write SetZeichnungskapital;
    property ZweiteZahlung     : TDateTime   read GetZweiteZahlung     write SetZweiteZahlung;
    property ZahlenderBetrag   : Double      read GetZahlenderBetrag   write SetZahlenderBetrag;
    property OnChange          : TNotifyEvent read FOnChange            write FOnChange;
  end;

var
  Gesellschafter     : TGesellschaftsname;
  GesellschafterListe : TList;
Nur kapiere ich das irgendwie mit dem Pointern noch nicht. Wie kann ich jetzt einen Wert aus der Klasse TGesellschaftsname auslesen ? Ich habe das vorher mit dem Record so gemacht :
Delphi-Quellcode:
TGesellschaftsname(GesellschafterListe[LV_Gesellschaftsform.Selected.Index]^).Gesellschaftsname
Nur mit der Klasse bekomme ich jetzt eine EAccessViolation. Wen ich jetzt hinten das Zeichen ^ weglasse passiert garnichts. Genauso mit dieser Zeile :
Delphi-Quellcode:
TGesellschaftsname(GesellschafterListe.Items[LV_Gesellschaftsform.Selected.Index]).Gesellschaftername
Was mache ich hier falsch ?

m.wollert 27. Dez 2009 17:49

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo,

ohne Dach (^) sollte es "eigentlich" klappen. Um genau den Fehler finden zu können, müsste etwas mehr Code her ;-)

Du arbeitest bei Klassen sowieso immer mit Adressen, auch wenn Du es nicht direkt mitbekommst. Deshalbt benötigst Du auch keine P-Referenz auf eine Instanz (So sehe ich das zumindest ;).

Du erzeugst vermutlich so:

Delphi-Quellcode:
Gesellschafter := TGesellschafter.Create;
GesellschafterListe := TList.Create;
Anschließend wirst Du vermutlich irgendwo so den Instanzzeiger speicher:
Delphi-Quellcode:
GesellschafterListe.Add(Gesellschafter);
Und hiermit greifst Du auf ein Element zu:
Delphi-Quellcode:
GesellschafterListe[Index];
Tipp: In einer Listview kannst Du auch mit ListItem.Data eine Referenz auf ein Objekt speichern.

Grüße :-)
Michael

RWarnecke 27. Dez 2009 18:23

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von m.wollert
Du erzeugst vermutlich so:

Delphi-Quellcode:
Gesellschafter := TGesellschafter.Create;
GesellschafterListe := TList.Create;

Ja das stimmt. Bei mir ist alles über mehrere Ereignisse von Komponenten verteilt. Deshalb habe ich nur die Deklaration geschrieben.
Zitat:

Zitat von m.wollert
Anschließend wirst Du vermutlich irgendwo so den Instanzzeiger speicher:
Delphi-Quellcode:
GesellschafterListe.Add(Gesellschafter);

Das ist auch richtig so. nach dem Add werden dann die Werte den einzelnen Properties der Klasse zuegordnet.
Zitat:

Zitat von m.wollert
Und hiermit greifst Du auf ein Element zu:
Delphi-Quellcode:
GesellschafterListe[Index];

Dann sollten die folgende Zeile ja eigentlich funktionieren :
Delphi-Quellcode:
with TGesellschaftsname(GesellschafterListe[LV_Gesellschaftsform.Selected.Index]) do
begin
  Edit1.Text := Gesellschaftername;
  { u.s.w. für die anderen Properties }
end;
Nur es funktioniert nicht :gruebel: Da war das mit dem Record ja doch einfacher.

Edit: Bevor die Frage kommt, was passiert. Mit diesem With-Do passiert garnichts. Es kommt kein Fehler und es wird auch nichts angezeigt.

m.wollert 27. Dez 2009 23:58

Re: Bei TList, Record auf Datenänderung reagieren
 
Hi,

versuche bitte mal folgendes:
  • Deklariere in der angesprochenen Methode eine lokale Variable vom Typ TGesellschaftsname
  • Erstelle eine Zeile: <lokale Variable> := GesellschafterListe[LV_Gesellschaftsform.Selected.Index];
  • Evtl. den With/Do-Block auskommentieren
  • Debugge nach der Zuweisung deine lokale Variable (Mauszeiger draufpacken und warten). Eigentlich müsste der Debugger anschließend alle Werte innerhalb der Instanz anzeigen. Alternativ kann es auch sein, dass Dein <Getter> nicht korrekt implementiert ist.

Wenn mehr Source da ist, kann auch besser geholfen werden. Poste doch am besten mal die komplette(n) Klasse(n) bzw. das Projekt.

Grüße :-)
Michael :-)

RWarnecke 28. Dez 2009 00:03

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo Michael,
danke für Deine Hilfe. Ich habe mittlerweile die Lösung selber gefunden. In der TList war überall der letzte Datensatz gespeichert. Das lag daran, dass ich die Klasse nicht für jeden Eintrag neu erstellt habe.
Wie ich das Problem gelöst hatte, habe ich mich noch in die TObjectList eingelesen und nun darauf alles umgestellt. Die TObjetList funktioniert sogar noch ein bisschen besser als die TList, von der Speicherverwaltung her. Das ganze sieht nun so aus. Meine Klassen-Deklaration aus Beitrag #10 und dann der folgende Sourcecode :
Delphi-Quellcode:
{...}

var
  GesellschafterListe : TObjectList;

// so erstelle ich die TObjectListe
  GesellschafterListe := TObjectList(true);

// so mache ich das mit jedem neuen Object für die Liste
  GesellschafterListe.Add(TGesellschaftsname.Create);
  TGesellschaftsname(GesellschafterListe.Last).OnChange := WertAenderung;
  TGesellschaftsname(GesellschafterListe.Last).StammNr :=
     StrToInt(LV_Kundendaten.Items.Item[LV_Kundendaten.Selected.Index].SubItems.Strings[1]);
  TGesellschaftsname(GesellschafterListe.Last).Gesellschaftername :=
     Edt_Gesellschaftsname.Text;

// so gebe ich die TObjectListe wieder frei
  GesellschafterListe.Free

{...}

procedure TMainForm.WertAenderung(Sender: TObject);
begin
  ShowMessage('Hier wird auf die Änderung reagiert');
end;
Das funktioniert alles so wie es soll. Ich habe jetzt nur noch eine Frage, muss ich für jedes Object, welches ich erstelle das OnChange-Ereignis neu zuweisen oder kann ich es auch einmal für die ganze ObjectListe zuweisen ?

m.wollert 28. Dez 2009 00:36

Re: Bei TList, Record auf Datenänderung reagieren
 
Hi Rolf,

ich definiere Eventhandler zu eigenen Klassen immer pro Instanz. Aber versuche Dich mal in Class Properties einzulesen. Damit sollte es global möglich sein.

Grüße nach Stuttgart :cheer:
Michael

wicht 28. Dez 2009 00:54

Re: Bei TList, Record auf Datenänderung reagieren
 
Oder:
Ableitung von TObjectList erstellen, da das OnChange Event dranpacken. Im Konstruktor von TGesellschaftsname gibst du die Liste mit. TGesellschaftsname kennt dann seine Liste und kann dann das Event an der Liste aufrufen (und sich vorher selbst der Liste hinzufügen), was du ja nur einmal im Programm an der Liste zuweisen musst. So wird die Liste eine Art Manager für die einzelnen Objekte, und es ist, finde ich, nicht unwahrscheinlich, dass man das gut gebrauchen kann, zum Beispiel für eine Funktion, die mit allen Objekten in der Liste irgendwas machen soll.
So hingetippselt, hoffe das funktioniert bzw. ist irgendwie unter Umständen hilfreich...

Delphi-Quellcode:
interface

type
  TGesellschafterListe = class;

  TGesellschafterListeChangeEvent = procedure(Sender: TObject; Obj: TGesellschaftsname) of object;

  TGesellschaftsname = class
  private
    FList: TGesellschafterListe;
  public
    procedure TriggerChange;
    constructor Create(List: TGesellschafterListe);
  end;

  TGesellschafterListe = class(TObjectList)
  private
    FOnChange: TGesellschafterListeChangeEvent;
  public
    property OnChange: TGesellschafterListeChangeEvent read FOnChange write FOnChange;
  end;

implementation

procedure TGesellschaftsname.Create(List: TGesellschafterListe);
begin
  inherited;
  FList := List;
  FList.Add(Self);
end;

procedure TGesellschaftsname.TriggerChange;
begin
  if Assigned(FList) then
    if Assigned(FList.OnChange) then
      FList.OnChange(FList, Self);
end;

procedure GesellschafterListeOnChange(Sender: TObject; Obj: TGesellschaftsname);
begin
  // Schnack, hier hat sich das Objekt "Obj" verändert
end;

var
  GesellschafterListe : TGesellschafterListe;
begin
  GesellschafterListe := TGesellschafterListe(True);
  GesellschafterListe.OnChange := GesellschafterListeOnChange;

  TGesellschaftsname.Create(GesellschafterListe);
  TGesellschaftsname.Create(GesellschafterListe);
  TGesellschaftsname.Create(GesellschafterListe);

  GesellschafterListe.Free;
end;

RWarnecke 31. Dez 2009 10:31

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo Alexander,

leider komme ich mit Deinem Beispiel nicht ganz klar. Dort tauchen zu viele Fehler auf. Deshalb habe ich mich jetzt mal selber dran versucht und bin zu folgendem Ergebnis gekommen :
Delphi-Quellcode:
type
  TForm8 = class(TForm)
    Btn_3: TButton;
    procedure Btn_3Click(Sender: TObject);
  private
    { Private declarations }
    procedure ListeChange(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form8: TForm8;

implementation

{$R *.dfm}

type
  TKlasse = class
  private
    FWert1 : Integer;
    FWert2 : string;
  public
    property Wert1 : Integer read FWert1;
    property Wert2 : string read FWert2;
  end;

  TCustomObjectList = class(TObjectList)
  private
    FOnChange : TNotifyEvent;
  protected
    function getItem(index: Integer): TKlasse; virtual;
    procedure setItem(index: Integer; Objekt: TKlasse); virtual;
  public
    function Add(Objekt: TKlasse):Integer; virtual;
    function Remove(Objekt: TKlasse):Integer; virtual;
    function IndexOf(Objekt: TKlasse):Integer; virtual;
    procedure Insert(index: Integer; Objekt: TKlasse); virtual;
    property Items[index: Integer]: TKlasse read getItem write setItem; default;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

procedure TForm8.Btn_3Click(Sender: TObject);
var
  Liste: TCustomObjectList;
begin
  Liste := TCustomObjectList.Create(True);
  Liste.OnChange := ListeChange;

  Liste.Add(TKlasse.Create);
  Liste.Add(TKlasse.Create);
  Liste.Add(TKlasse.Create);
  Liste.Add(TKlasse.Create);

  Liste.Free;
end;

procedure TForm8.ListeChange(Sender: TObject);
begin
  ShowMessage('Ein neues Object hinzugefügt !!');
end;

{ TCustomObjectList }

function TCustomObjectList.Add(Objekt: TKlasse): Integer;
begin
  Result := inherited Add(Objekt);
  if Assigned(FOnChange) then
    FOnChange(Self)
end;

function TCustomObjectList.getItem(index: Integer): TKlasse;
begin
  Result := TKlasse(inherited Items[Index]);
end;

function TCustomObjectList.IndexOf(Objekt: TKlasse): Integer;
begin
  Result := inherited IndexOf(Objekt);
end;

procedure TCustomObjectList.Insert(index: Integer; Objekt: TKlasse);
begin
  inherited Insert(Index, Objekt);
end;

function TCustomObjectList.Remove(Objekt: TKlasse): Integer;
begin
  inherited Remove(Objekt);
end;

procedure TCustomObjectList.setItem(index: Integer; Objekt: TKlasse);
begin
  inherited Items[index] := Objekt;
end;
Das funktioniert auch soweit. Nur was muss ich machen, dass ich im OnChange Ereignis auf die Werte der Klasse zugreifen kann, die gerade in die ObjectListe eingefügt wurde ?

taaktaak 1. Jan 2010 11:36

Re: Bei TList, Record auf Datenänderung reagieren
 
Hallo Rolf,
du koenntest z.B. anstelle des simplen Notify-Events einen eigenen Event-Typ definieren und dann den/die veraenderten Werte in deinem speziellen OnChange() mitliefern.

RWarnecke 1. Jan 2010 12:04

Re: Bei TList, Record auf Datenänderung reagieren
 
Moin Ralph und frohes neues Jahr, kurz gefragt, wie schreibt man sich sein eigenes Event ? Stecke nämlich noch in den Kinderschuhen bei solchen Sachen. Geht das vielleicht in Richtung Windows Messages ?

m.wollert 1. Jan 2010 14:28

Re: Bei TList, Record auf Datenänderung reagieren
 
Hi Rolf,

http://www.delphipraxis.net/internal...=553654#553654

Grüße :-)
Michael

RWarnecke 26. Jan 2010 19:57

Re: Bei TList, Record auf Datenänderung reagieren
 
So sieht mein Versuch aus. Nur leider schaffe ich es nicht,
Delphi-Quellcode:
  TGesellschafterChangeEvent = procedure(Sender: TObject; Obj: TGesellschaftsname) of object;

  TGesellschafterObjListe = class(TObjectList)
  private
    FOnChange : TGesellschafterChangeEvent;
  protected
    function getItem(Index: Integer): TGesellschaftsname; virtual;
    procedure setItem(Index: Integer; Objekt: TGesellschaftsname); virtual;
  public
    function Add(Objekt: TGesellschaftsname): Integer; virtual;
    function NewRecord(Objekt: TGesellschaftsname): Integer; virtual;
    function Remove(Objekt: TGesellschaftsname): Integer; virtual;
    function IndexOf(Objekt: TGesellschaftsname): Integer; virtual;
    procedure Insert(Index: Integer; Objekt: TGesellschaftsname); virtual;
    property Items[index: Integer]: TGesellschaftsname read getItem write setItem; default;
    property OnChange: TGesellschafterChangeEvent read FOnChange write FOnChange;
  end;

{...}

procedure TMainForm.GesellschafterListeChange(Sender: TObject; Obj: TGesellschaftsname);
begin
  with DM_Main.UniQuery_Temp do
  begin
    SQL.Text := 'EXECUTE PROCEDURE SP_NEW_GESELLSCHAFTER (:stammnr, :name, :B1, :B2, :D2);';
    ParamByName('StammNr').AsInteger := Obj.StammNr;
    ParamByName('Name').AsString := Obj.Gesellschaftername;
    ParamByName('B1').AsFloat := Obj.Zeichnungskapital;
    ParamByName('B2').AsFloat := Obj.ZahlenderBetrag;
    ParamByName('D2').AsDateTime := Obj.ZweiteZahlung;
    Execute;
  end;
end;

{...}

function TGesellschafterObjListe.Add(Objekt: TGesellschaftsname): Integer;
begin
  Result := inherited Add(Objekt);
end;

function TGesellschafterObjListe.getItem(Index: Integer): TGesellschaftsname;
begin
  Result := TGesellschaftsname(inherited Items[Index]);
end;

function TGesellschafterObjListe.IndexOf(Objekt: TGesellschaftsname): Integer;
begin
  Result := inherited IndexOf(Objekt);
end;

procedure TGesellschafterObjListe.Insert(Index: Integer; Objekt: TGesellschaftsname);
begin
  inherited Insert(Index, Objekt);
end;

function TGesellschafterObjListe.NewRecord(Objekt: TGesellschaftsname): Integer;
begin
  Result := inherited Add(Objekt);
  if Assigned(FOnChange) then
    FOnChange(Self, Objekt);
end;

function TGesellschafterObjListe.Remove(Objekt: TGesellschaftsname): Integer;
begin
  Result := inherited Remove(Objekt);
end;

procedure TGesellschafterObjListe.setItem(Index: Integer; Objekt: TGesellschaftsname);
begin
  inherited Items[Index] := Objekt;
  if Assigned(FOnChange) then
    FOnChange(Self, Objekt);
end;
Das ChangeEvent wird nicht ausgeführt, wenn ich einen Wert ändere. Wenn ich NewRecord ausführe, dann wird das Change-Event ausgeführt, aber in Obj stehen keine Werte aus der Klasse. Kann mir da jemand bitte weiterhelfen, denn ich weiß nichtmehr weiter.

himitsu 26. Jan 2010 20:56

Re: Bei TList, Record auf Datenänderung reagieren
 
Wozu ist denn alles als virtual deklariert?
Bringt zu diesem Zeitpunkt eh nix mehr.

Wird auch überall TGesellschafterObjListe verwendet und nicht TObjectList/TList?
TList kennt deine Änderungen ja nicht.

Ich würde eher Notify über schreiben und dort das OnChange-Event auslösen, da kommen alle Meldungen (hinzugefügt/gelöscht) vorbei.
Delphi-Quellcode:
protected
  procedure Notify(Ptr: Pointer; Action: TListNotification); override;

RWarnecke 26. Jan 2010 21:06

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von himitsu
Wozu ist denn alles als virtual deklariert?
Bringt zu diesem Zeitpunkt eh nix mehr.

Wird auch überall TGesellschafterObjListe verwendet und nicht TObjectList/TList?
TList kennt deine Änderungen ja nicht.

Ich würde eher Notify über schreiben und dort das OnChange-Event auslösen, da kommen alle Meldungen (hinzugefügt/gelöscht) vorbei.
Delphi-Quellcode:
protected
  procedure Notify(Ptr: Pointer; Action: TListNotification); override;

Hallo himitsu,

ich kann Dir leider nicht ganz folgen mit dem Notify. Kannst Du mir das bitte mal an einem praktischen Beispiel erklären ?

himitsu 26. Jan 2010 21:34

Re: Bei TList, Record auf Datenänderung reagieren
 
TObjectList nutzt dieses z.B. um Objekte freizugeben
Delphi-Quellcode:
procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if OwnsObjects then
    if Action = lnDeleted then
      TObject(Ptr).Free;
  inherited;
end;
du überschreibst es und macht z.B. sowas
Delphi-Quellcode:
procedure TGesellschafterObjListe.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if (Action = lnAddted) and Assigned(FOnChange) then
    FOnChange(Self, TGesellschaftsname(Ptr));
  inherited;
end;
PS: OnChange reagiert so nur auf Änderungen der Liste,
wenn auch z.B. auf Änderungen/Zuweisungen in/an .Zeichnungskapital reagert werden soll,
dann muß dieses in TGesellschaftsname abgefangen und an die TGesellschafterObjListe weitergereicht werden.

RWarnecke 26. Jan 2010 21:44

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von himitsu
TObjectList nutzt dieses z.B. um Objekte freizugeben
Delphi-Quellcode:
procedure TObjectList.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if OwnsObjects then
    if Action = lnDeleted then
      TObject(Ptr).Free;
  inherited;
end;
du überschreibst es und macht z.B. sowas
Delphi-Quellcode:
procedure TGesellschafterObjListe.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if (Action = lnAddted) and Assigned(FOnChange) then
    FOnChange(Self, TGesellschaftsname(Ptr));
  inherited;
end;

Ok, den Teil mit dem Notify habe ich kapiert, hoffe ich. :?

Zitat:

Zitat von himitsu
PS: OnChange reagiert so nur auf Änderungen der Liste,
wenn auch z.B. auf Änderungen/Zuweisungen in/an .Zeichnungskapital reagert werden soll,
dann muß dieses in TGesellschaftsname abgefangen und an die TGesellschafterObjListe weitergereicht werden.

Wäre das sowas wie in Beitrag #16 von wicht ?

himitsu 26. Jan 2010 22:00

Re: Bei TList, Record auf Datenänderung reagieren
 
Zitat:

Zitat von RWarnecke
Wäre das sowas wie in Beitrag #16 von wicht ?

Ja, nur würde ich, bezüglich einer besseren Trennung, eine Protected-Methode "DoChange" in TGesellschafterObjListe einfügen und dann bei Veränderungen in TGesellschaftsname dieses aufrufen
Delphi-Quellcode:
if Assigned(FList) then
  FList.DoChange(Self);
Delphi-Quellcode:
procedure TGesellschafterObjListe.DoChange(Sender: TGesellschaftsname);
begin
  if Assigned(FOnChange) then
    FOnChange(Self, Sender);
end;

procedure TGesellschafterObjListe.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if Action = lnAddted then
    DoChange(TGesellschaftsname(Ptr));
  inherited;
end;

RWarnecke 26. Jan 2010 22:09

Re: Bei TList, Record auf Datenänderung reagieren
 
Ich habe doch nochmal eine Frage zu Notify. Ich habe die Procedure genau so geschrieben wie Du in Deinem Beitrag. Wenn ich jetzt in dem ChangeEvent die Werte mitprotokollieren, sind alle Werte aus der Klasse leer. Entferne ich die Abfrage auf die Action, dann bekomme ich in dem Protokoll erst die leeren Werte angezeigt und danach dann die Werte die ich eingefügt habe in umgekehrter Reihenfolge. Also den letzten zuerst u.s.w. Kann man das noch irgendwie bereinigen ?

Zitat:

Zitat von mit Action = lnAdded
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:

Zitat:

Zitat von ohne Action = lnAdded
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:
Wert 1: 0 - Wert 2:
Wert 1: 40 - Wert 2: Test 4
Wert 1: 30 - Wert 2: Test 3
Wert 1: 20 - Wert 2: Test 2
Wert 1: 10 - Wert 2: Test 1



Alle Zeitangaben in WEZ +1. Es ist jetzt 00:32 Uhr.

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