Delphi-PRAXiS
Seite 2 von 3     12 3      

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)

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


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

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