2015-10-02 119 views
1

(TObjectList)的對象可以知道(TMyObject)的某些值何時發生了更改?對象發生變化時通知TObjectList

一些示例:

TMyObject = class 
    oName: string; 
end; 

TMyObjectList = class(TObjectList<TMyObject>) 
end; 

procedure Form1.Button1.Click(Sender: TObject); 
var 
    Obj: TMyObject; 
    List: TMyObjectList; 
Begin 
List:= TMyObjectList.Create; 
Obj:= TMyObject.Create; 
List.Add(Obj); 
List[0].oName:= 'Test'; // here a want to know from var (List) when this object (Obj or List[0]) changed his value.. 
end; 

感謝您的幫助。

回答

6

我剛剛將TObservableList<T>類型添加到Spring4D(feature/observablelist分支)。它主要是在.NET之後建模的,並使用INotifyPropertyChanged接口將其事件處理程序附加到支持它的任何對象。這個類已經有相當一段時間的DSharp的一部分,並在生產中使用。它可能會在未來發生一些變化,併成爲圖書館的完整部分。

這裏是一個小例子如何使用它,所以你得到一個想法:

program Project60; 

{$APPTYPE CONSOLE} 

uses 
    Spring, 
    Spring.Collections, 
    SysUtils; 

type 
    TNotifyPropertyChangedBase = class(TInterfaceBase, INotifyPropertyChanged) 
    private 
    fOnPropertyChanged: Event<TPropertyChangedEvent>; 
    function GetOnPropertyChanged: IPropertyChangedEvent; 
    protected 
    procedure PropertyChanged(const propertyName: string); 
    end; 

    TMyObject = class(TNotifyPropertyChangedBase) 
    private 
    fName: string; 
    procedure SetName(const Value: string); 
    public 
    property Name: string read fName write SetName; 
    end; 

    TMain = class 
    procedure ListChanged(Sender: TObject; const item: TMyObject; 
     action: TCollectionChangedAction); 
    end; 

{ TNotifyPropertyChangedBase } 

function TNotifyPropertyChangedBase.GetOnPropertyChanged: IPropertyChangedEvent; 
begin 
    Result := fOnPropertyChanged; 
end; 

procedure TNotifyPropertyChangedBase.PropertyChanged(
    const propertyName: string); 
begin 
    fOnPropertyChanged.Invoke(Self, 
    TPropertyChangedEventArgs.Create(propertyName) as IPropertyChangedEventArgs); 
end; 

{ TMyObject } 

procedure TMyObject.SetName(const Value: string); 
begin 
    fName := Value; 
    PropertyChanged('Name'); 
end; 

{ TMain } 

procedure TMain.ListChanged(Sender: TObject; const item: TMyObject; 
    action: TCollectionChangedAction); 
begin 
    case action of 
    caAdded: Writeln('item added ', item.Name); 
    caRemoved, caExtracted: Writeln('item removed ', item.Name); 
    caChanged: Writeln('item changed ', item.Name); 
    end; 
end; 

var 
    main: TMain; 
    list: IList<TMyObject>; 
    o: TMyObject; 
begin 
    list := TCollections.CreateObservableList<TMyObject>; 
    list.OnChanged.Add(main.ListChanged); 
    o := TMyObject.Create; 
    o.Name := 'o1'; 
    list.Add(o); 
    o := TMyObject.Create; 
    o.Name := 'o2'; 
    list.Add(o); 
    list[1].Name := 'o3'; 
    Readln; 
end. 
2

沒有什麼內置的可以做你所要求的。您需要自己實施通知機制。這是Observer Pattern的經典場景。

這種模式有許多實現已經存在。一個明顯的選擇是在Spring4D中使用實現。尼克霍奇斯最近的書,More Coding in Delphi,包括這一模式,我會推薦一章。

+0

謝謝,這也許幫助。在TObjectList中發現(OnNotify/Notify)方法,這不能用於解決我的問題? – scribe

+0

不,他們對你沒用。我相信你可以從文檔中看到爲什麼。 –

+0

感謝您的推薦,@DavidHeffernan! –

-1

發現的方式,如何從TMyObject調用TObjectList的方法。在基礎對象中使用TNotifyEvent。

例子:

TMyClass = class(TObject) 
private 
    FName: string; 
    FOnNameEvent: TNotifyEvent; 
    procedure SetName(value: string); 
public 
    property Name: string read FName write SetName; 
    property OnNameEvent: TNotifyEvent read FOnNameEvent write FOnNameEvent; 
end; 

procedure TMyClass.SetName(value: string); 
begin 
    FName := value; 
    if Assigned(FOnNameEvent) then 
    FOnNameEvent(Self); 
end; 

procedure MyNameEvent(Sender: TObject); 
var 
    i: Integer; 
begin 
    for i := 0 to MyListOfMyClassObjects.Count -1 do 
    if Sender = MyListOfMyClassObjects.Item[i] then 
    begin 
     MessageBox(0, PChar(TMyClass(MyListOfMyClassObjects.Item[i]).Name), nil, MB_OK); 
     break; 
    end; 
end; 

procedure MyProc; 
var 
    MyObject: TMyClass; 
begin 
    MyObject := TMyClass.Create; 
    MyObject.OnNameEvent := MyNameEvent; 
    MyListOfMyClassObjects.Add(MyObject); 
end; 
+0

另外:事件的過程必須是某個對象的方法。 – scribe

相關問題