当Object改变时通知TObjectList

时间:2015-10-02 07:56:53

标签: delphi

(TObjectList)的对象可以知道(TMyObject)的某些值何时被更改?

一些例子:

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;

感谢您的帮助。

3 个答案:

答案 0 :(得分:7)

我刚刚将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.

答案 1 :(得分:2)

没有任何东西可以做你所要求的。您需要自己实施通知机制。这是Observer Pattern的经典场景。

这种模式的许多实现已经存在。一个显而易见的选择是在Spring4D中使用该实现。尼克霍奇斯最近出版的书More Coding in Delphi,包括了我将推荐的关于这种模式的章节。

答案 2 :(得分:-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;