![]() |
Delphi-Version: XE2
Ein Object in TObjectList<T> löschen mit Ereignis
Hallo zusammen,
ich habe folgende Klassen erstellt :
Delphi-Quellcode:
Das funktioniert auch alles soweit ganz gut, bis auf den Teil mit FOnDelete. Warum bekomme ich jedesmal bei der Zeile
type
TModifyActionList = (lnNone, lnAdded, lnChange, lnDelete); TDegree = class private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FID : Integer; FDegree : string; procedure SetID(const Value: Integer); procedure SetDegree(const Value: string); public property ID : Integer read FID write SetID; property Degree : string read FDegree write SetDegree; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write FOnChange; property OnDelete : TNotifyEvent read FOnDelete write FOnDelete; end; TCustomObjectList<T: class> = class(TObjectList<T>) private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FNewRecord : Boolean; procedure DeleteRecord(Klasse: T); protected function getItem(Index: Integer): T; virtual; procedure setItem(Index: Integer; Objekt: T); virtual; procedure Notify(const Item: T; Action: TCollectionNotification); override; public function Add(Objekt: T): Integer; virtual; function NewRecord(Objekt: T): Integer; virtual; function Remove(Objekt: T): Integer; virtual; function IndexOf(Objekt: T): Integer; virtual; procedure Insert(Index: Integer; Objekt: T); virtual; property Items[index: Integer]: T read getItem write setItem; default; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write FOnChange; property OnDelete : TNotifyEvent read FOnDelete write FOnDelete; end; {...} { TDegree } procedure TDegree.SetDegree(const Value: string); begin FDegree := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; procedure TDegree.SetID(const Value: Integer); begin FID := Value; if (Assigned(FOnChange)) and (FModifyAction = lnChange) then FOnChange(Self); end; { TCustomObjectList<T> } function TCustomObjectList<T>.Add(Objekt: T): Integer; begin FNewRecord := False; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.DeleteRecord(Klasse: T); begin // To do something end; function TCustomObjectList<T>.getItem(Index: Integer): T; begin Result := T(inherited Items[Index]); end; function TCustomObjectList<T>.IndexOf(Objekt: T): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T); begin inherited Insert(Index, Objekt); end; function TCustomObjectList<T>.NewRecord(Objekt: T): Integer; begin FNewRecord := True; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Notify(const Item: T; Action: TCollectionNotification); begin if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then begin FNewRecord := False; FOnChange(Self); end; if Action = cnRemoved then begin FOnDelete(Item); end; inherited Notify(Item, Action); end; function TCustomObjectList<T>.Remove(Objekt: T): Integer; begin Result := inherited Remove(Objekt); end; procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T); begin inherited Items[Index] := Objekt; end;
Delphi-Quellcode:
eine AccessViolation ? Wie kann ich das beheben und was habe ich falsch gemacht ?
FOnDelete(Item);
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Prüf doch mal mit
Delphi-Quellcode:
ab, ob da was zugewiesen ist ;)
if Assigned( FOnDelete ) then
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Habe ich das aus der OH für Assigned richtig verstanden, wenn ich folgende Zeilen Code chreibe :
Delphi-Quellcode:
Dann gibt mir
Degree := TDegree.Create;
Degree.OnChange := TableEntryChange; Degree.OnDelete := TableEntryDelete; Degree.ID := FieldByName('ID').AsInteger; Degree.Degree := FieldByName('Degree').AsString; DegreeList.Add(Degree);
Delphi-Quellcode:
innerhalb der Klasse zurück, ob die Zeile
Assigned(FOnDelete)
Delphi-Quellcode:
ausgeführt wurde oder nicht ? Wenn ja, dann ist es leider nicht der Fall.
Degree.OnDelete := TableEntryDelete;
Delphi-Quellcode:
gibt immer False zurück. Warum ?
Assigned(FOnDelete)
Der obere Code-Iteil wird in einer Schleife mehrmals wiederholt. |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Eigentlich sollte Assigned nach der Methodenzuweisung true zurückliefern. Bau doch mal temporär einen Setter ein, setz dort einen Haltepunkt und schau, ob der angesprungen wird. Ich sehe in dem Code keinen Grund, wieso das nicht so sein sollte.
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Bei den Klassen geht er in den Setter und weißt auch den richtigen Wert zu. Kann es vielleicht daran liegen, dass erst der Delete-Befehl ausgeführt wird und er dann ins Notify springt von TCustomObjectList<T: class> ?
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Ich habe es gerade nicht im Kopf, aber möglicherweise ist das Item zwischen dem Delete und dem Notify bereits freigegeben, das würde die AV erklären.
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe es jetzt mal getestet. Wenn ich bei der Zeile
Delphi-Quellcode:
einen Breakpoint setze, steht der Count von der ObjectList um einen reduziert. Das heißt für mich, dass erst das Objekt gelöscht wird und dann Notify ausgeführt wird. Um das Ergebnis noch zu verifizieren, habe ich die Procedure Delete mit in meine abgeleitet Klasse übernommen. Es ist wirklich so, das erst die Delete Procedure ausgeführt wird und dann das Notify. Ich habe jetzt mal zusätzlich in der Delete-Procedure eine Abfrage auf Assigned(FOnDelete) gemacht. Auch hier wird ein False ausgegeben, wie kann das sein ?
if Action = cnRemoved then
Meine TCustomObjectList<T: class> sieht jetzt so aus :
Delphi-Quellcode:
Bei
TCustomObjectList<T: class> = class(TObjectList<T>)
private FOnChange : TNotifyEvent; FOnDelete : TNotifyEvent; FModifyAction : TModifyActionList; FNewRecord : Boolean; procedure SetOnDelete(const Value: TNotifyEvent); procedure SetOnChange(const Value: TNotifyEvent); protected function getItem(Index: Integer): T; virtual; procedure setItem(Index: Integer; Objekt: T); virtual; procedure Notify(const Item: T; Action: TCollectionNotification); override; public function Add(Objekt: T): Integer; virtual; procedure Delete(Index: Integer); virtual; function NewRecord(Objekt: T): Integer; virtual; function Remove(Objekt: T): Integer; virtual; function IndexOf(Objekt: T): Integer; virtual; procedure Insert(Index: Integer; Objekt: T); virtual; property Items[index: Integer]: T read getItem write setItem; default; property ModifyAction : TModifyActionList read FModifyAction write FModifyAction; property OnChange : TNotifyEvent read FOnChange write SetOnChange; property OnDelete : TNotifyEvent read FOnDelete write SetOnDelete; end; {...} { TCustomObjectList<T> } function TCustomObjectList<T>.Add(Objekt: T): Integer; begin FNewRecord := False; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Delete(Index: Integer); begin if Assigned(FOnDelete) then FOnDelete(Self); inherited Delete(Index); end; function TCustomObjectList<T>.getItem(Index: Integer): T; begin Result := T(inherited Items[Index]); end; function TCustomObjectList<T>.IndexOf(Objekt: T): Integer; begin Result := inherited IndexOf(Objekt); end; procedure TCustomObjectList<T>.Insert(Index: Integer; Objekt: T); begin inherited Insert(Index, Objekt); end; function TCustomObjectList<T>.NewRecord(Objekt: T): Integer; begin FNewRecord := True; Result := inherited Add(Objekt); end; procedure TCustomObjectList<T>.Notify(const Item: T; Action: TCollectionNotification); begin if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then begin FNewRecord := False; FOnChange(Self); end; inherited Notify(Item, Action); end; function TCustomObjectList<T>.Remove(Objekt: T): Integer; begin Result := inherited Remove(Objekt); end; procedure TCustomObjectList<T>.setItem(Index: Integer; Objekt: T); begin inherited Items[Index] := Objekt; end; procedure TCustomObjectList<T>.SetOnChange(const Value: TNotifyEvent); begin FOnChange := Value; end; procedure TCustomObjectList<T>.SetOnDelete(const Value: TNotifyEvent); begin FOnDelete := Value; end;
Delphi-Quellcode:
steht der Count von TCustomObjectList<TDegree> noch auf der vollen Anzahl Objekte. Entweder verstehe ich hier etwas nicht oder es läuft irgendwas schief.
if Assigned(FOnDelete) then
Edit: Im Anhang meine DegreeList, nach dem Befüllen mit Daten. So wie ich das sehe, ist doch alles korrekt oder ? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Was sagt denn der debugger, wenn du dir kurz vor dem aufruf den Wert dieser Variable anzeigen läßt? |
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Zitat:
Debugger Exception Notification --------------------------- Project Project14.exe raised exception class $C0000005 with message 'access violation at 0x00000000: read of address 0x00000000'. --------------------------- Break Continue Help --------------------------- Zitat:
|
AW: Ein Object in TObjectList<T> löschen mit Ereignis
Delphi-Quellcode:
1) aber vemutlich wirklich ein "nil".
if (Assigned(FOnChange)) and (FNewRecord) and (Action <> cnRemoved) then // hier hast'e geprüft
begin FNewRecord := False; FOnChange(Self); end; if Action = cnRemoved then // hier nicht begin FOnDelete(Item); // hier haltepunkt hin und schauen was in FOnDelete steht, *1 end; Jedenfalls sieht die Exception danach aus, da dort zur Adresse 0 (nil) gesprungen wurde und weil dort kein ausführbarer Code steht, knallt es. (aber natürlich kann es auch noch innerhalb einer verlinkten Methode knallen, aber da sollte der Debugger ebenfalls hilfreich sein) Der schon genannte Trick mit dem Setter würde zmindestens zeigen, ob, wann und wo dieses Property verändert wird. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:31 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