Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Änderungen in TList verfolgen (https://www.delphipraxis.net/120381-aenderungen-tlist-verfolgen.html)

taaktaak 10. Sep 2008 09:02


Änderungen in TList verfolgen
 
Moin, Moin.

Bin dabei eine neue Stringgrid-Komponente zu entwerfen. Die Daten werden nicht im Grid, sondern in einer TList vorgehalten. Dafür ist eine Interaktion zwischen der Liste und dem Grid notwendig: So muss z.B. das sortierte Grid erfahren, wenn Datensätze in TList aufgenommen oder gelöscht wurden.

Zuerst war mein Ansatz, die Methoden Add, Extract und Delete in einer Ableitung von TList zu überschreiben und darin meine Benachrichtigung an das Grid einzufügen. Geht aber nicht: "Statische Methoden können nicht überschrieben werden". Hm, dann bin ich in CLASSES über eine "leere" Prozedur von TList gestolpert, die in der Hilfe nicht erwähnt wird: TList.Notify() - damit geht es auch, sehr schön :-D

Delphi-Quellcode:
TrzGridList = class(TList)
                public
                  procedure Notify (Ptr:Pointer;Action:TListNotification); override;
                end;

procedure TrzGridList.Notify(Ptr:Pointer;Action:TListNotification);
begin
  case Action of
   lnAdded  : ShowMessage('data added');
   lnDeleted : ShowMessage('data deleted');
   end
  // sehr schön,
  // aber welche Liste hat die Info nun gesendet?
end;
Nun gibt es aber doch noch ein kleines Problem: Das Grid arbeitet mit zwei Listen. Eine enthält alle Datensätze, die zweite Liste nur die gefilterten Datensätze. Es ist daher notwendig, in der Notify-Prozedur den "Sender" des Events zu ermitteln. Tja, und da hab' ich im Augenblick keine Ahnung wie ich an diese Information herankomme?

toms 10. Sep 2008 09:08

Re: Änderungen in TList verfolgen
 
Hallo,

Kann man den Sender nicht via TObject(Ptr) ermitteln?

taaktaak 10. Sep 2008 09:15

Re: Änderungen in TList verfolgen
 
Moin toms,
der übergebene Pointer ist der Zeiger auf das z.B. an TList.Add() übergebene Datenobjekt :cry:

taaktaak 10. Sep 2008 10:23

Re: Änderungen in TList verfolgen
 
Bauingenieure sind ja für pragmatische, nicht unbedingt elegante Lösungen bekannt. Für die Eleganz sind die Architekten zuständig:
2 notwendige Listen > 2 individuelle Ableitungen von TList > jede Liste erhält damit ein eigenes Notify().
Passt!
Problem beseitigt!

Roachford 10. Sep 2008 11:28

Re: Änderungen in TList verfolgen
 
Du hast beide Listen und du hast 2 Member die jeweils eine Instanz halten. Warum vergleichst du somit nicht einfach die Listeninstanzen?

taaktaak 10. Sep 2008 11:42

Re: Änderungen in TList verfolgen
 
Moin Roachford.
Nun genau das war mein Ansinnen. Es fehlt mir allerdings der konkrete Ansatz dies zu tun. Habe ein "Self.InstanceSize()" gefunden, aber kein "Self.InstanceName()". Mit welchem Kriterium bzw. Attribut kann ich also die beiden Instanzen unterscheiden?

sirius 10. Sep 2008 12:04

Re: Änderungen in TList verfolgen
 
Ich weiß nicht worauf du genau hinaus willst. Du könntest natürlich deiner Klasse TrzGridList noch eine Eigenschaft Name geben und diese im constructor setzen. Nur ich denke, das ist nicht der elegante Weg.

Edit:
Anders gesagt: Was machst du im Notify, wenn du gerade nicht eine NAchricht anzeigen willst?

Roachford 10. Sep 2008 12:51

Re: Änderungen in TList verfolgen
 
Delphi-Quellcode:
  TListNotifyEvent = procedure(AList: TObject; const AAction: TListNotification; const AElement: TObject) of object;
  TListDescendant = class(TList)
  private
    FOnNotify: TListNotifyEvent;
  protected
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  public
    property OnNotify: TListNotifyEvent read FOnNotify write FOnNotify;
  end;

...

procedure TListDescendant.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if assigned(FOnNotify) then
    FOnNotify(Self, Action, TObject(Ptr));

  inherited;
end;
Delphi-Quellcode:
  TMyGrid = class(TCustomGrid)
  private  
    fFilteredList: TListDescendant;
    fOtherList: TListDescendant;

  protected
    Procedure ListNotifier(AList: TObject; const AAction: TListNotification; const AElement: TObject);

  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

...

constructor TMyGrid.Create(AOwner: TComponent);
begin
  inherited;

  fFilteredList := TListDescendant.Create;
  fFilteredList.OnNotify := ListNotifier;
  fOtherList := TListDescendant.Create;
  fOtherList.OnNotify := ListNotifier;
end;

destructor TMyGrid.Destroy;
begin
  fFilteredList.Free;
  fOtherList.Free;

  inherited;
end;

procedure TMyGrid.ListNotifier(AList: TObject; const AAction: TListNotification; const AElement: TObject);
begin
  if AList = fFilteredList then
    // gefilterte Liste
  else if AList = fOtherList then
    // die andere Liste

  ODER

  Liste := TListDescendant(AList);
end;
Es gibt auch noch die Möglichkeit, dass die Liste direkt wissen von TMyGrid hat und direkt von diesem z.B. eine Methode aufruft über das friend-Verhalten innerhalb der Unit, aber das ist zum einen schlechter Stil und zum anderen kann man dann schlecht erweitern, also mal ein abgeleitetes TMyGrid einsetzen etc. Da sind die Eventhandler deutlich flexibler und es werden keine OOP Konzepte eingerissen (wie bei Friend-Prinzip) - ausser natürlich durch die Closure's an sich, welche CodeGear genau dazu eingeführt hat.

taaktaak 10. Sep 2008 13:13

Re: Änderungen in TList verfolgen
 
Hallo Roachford!

Ja, was soll ich sagen? Wenn es jetzt so mundgerecht von dir präsentiert wird, frage ich mich, warum ich nicht selbst darauf gekommen bin. Das naheliegenste ist doch tatsächlich eine eigene Name-Property der Liste. Die Verwendung eines zusätzlichen Listen-Events, welches dann die Information von Notify() weiterleitet und eine Auswertung des Absenders innerhalb des Grids ermöglicht - na klar! Diese Variante werde ich verwenden! Vielen herzlichen Dank für deine Bemühungen :hi:

Zur Frage (von sirius):

Derzeit benötige ich im Grid nur die Information, dass sich die Liste geändert hat. Dann wird darauf reagiert, dass ein ggf. gesetzter Filter oder eine vorgenommene Sortierung nicht mehr aktuell sind. Aber vielleicht steigen die Anforderungen ja noch, bin derzeit noch beim "gemütlichen basteln".


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:18 Uhr.

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