Ich würde der „Datenklasse“ (unten „Item“) sowie der Klasse „Test“ einfach ein Event OnChanged respektive OnItemChanged (oder so ähnlich) verpassen. „Test“ registriert automatisch für alle seine Items den OnChanged-Handler, und leitet die dort „abgefangenen“ Events dann über OnItemChanged nach außen weiter.
Delphi-Quellcode:
type
TItem = class
protected
FOnChanged: TNotifyEvent;
procedure SetValue(const AValue: integer);
public
property Value: integer read FValue write SetValue;
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
end;
// Typensichere Objektliste, oder unter neueren Versionen TList<Item>
TItemList = class(TObjectList) {…} end;
TOnItemChanged = procedure (Sender: TObject; Item: TItem) of object;
TTest = class
protected
FList: TItemList;
FOnItemChanged: TOnItemChanged;
procedure HandleItemChanged(Sender: TObject);
public
property OnItemChanged: TOnItemChanged read FOnItemChanged write FOnItemChanged;
property List: TItemList read FList;
procedure LoadData;
end;
implementation
procedure TItem.SetValue(const AValue: integer);
begin
FValue := AValue;
if Assigned(OnChanged) then
OnChanged(self);
end;
procedure TTest.HandleItemChanged(Sender: TObject);
begin
{ …eventuell noch selbst irgendwas tun?… }
if Assigned(OnItemChanged) then
OnItemChanged(self, Sender as TItem);
end;
procedure TTest.LoadData;
var
i: integer;
function MakeItem(Value: integer): TItem
begin
Result := TItem.Create;
// wichtig:
Result.OnChanged := HandleItemChanged;
Result.Value := Value;
end;
begin
for i := 0 to 42 do
FList.Add(MakeItem(i));
end;
Delphi-Quellcode:
type
TMyForm = class(TForm)
{…}
Listview: TListView;
protected
FTest: TTest;
procedure HandleItemChanged(Sender: TObject; Item: TItem);
end;
implementation
procedure HandleItemChanged(Sender: TObject; Item: TItem);
begin
{ … Listview neuzeichnen (bzw. nur das jeweilige Item) … }
end;
procedure TMyForm.FormCreate({…})
begin
FTest := TTest.Create;
FTest.OnItemChanged := HandleItemChanged;
end;
Das Beispiel habe ich hier nur eben hier im Beitragseditor runtergeschrieben. Es gibt natürlich noch ein paar Dinge, die man in einer echten Anwendung sauberer lösen könnte/müsste (z.B. sollte TItemList irgendein Ereignis bereitstellen, wenn neue Items hinzugefügt werden, damit deren OnChanged-Handler gleich automatisch belegt werden kann), aber es geht hier ja nur um das grobe Prinzip...
Wenn das
GUI an mehreren Stellen gleichzeitig aktualisiert werden muss, musst du statt Events das Observer-Pattern implementieren (*hust* deshalb wären Multicast-Events toll *hust*).