1

当对象更改为使用 IList 时,我从 Notify the TObjectList 中修改了@Stefan Glienkes 示例,因为我在列表中使用了接口对象。在事件处理程序中,我可以处理 caAdded 和 caRemoved 事件,但没有发出 caChanged 信号。

这是设计使然还是我在某个地方犯了错误?

此示例显示了行为:

program Project61;

{$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;

  IMyInterface = interface(IInterface)
    ['{D5966D7D-1F4D-4EA8-B196-CB9B39AF446E}']
    function GetName: String;
    procedure SetName(const Value: String);
    property Name: String read GetName write SetName;
  end;

  TMyObject = class(TNotifyPropertyChangedBase, IMyInterface)
  private
    FName: string;
    function GetName: string;
    procedure SetName(const Value: string);
  public
    property Name: string read GetName write SetName;
  end;

  TMain = class
    procedure ListChanged(Sender: TObject; const item: IMyInterface;
      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;

function TMyObject.GetName: string;
begin
  Result := FName;
end;

{ TMain }

procedure TMain.ListChanged(Sender: TObject; const item: IMyInterface;
  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<IMyInterface>;
  o   : IMyInterface;

begin
  list := TCollections.CreateList<IMyInterface>;
  list.OnChanged.Add(main.ListChanged);
  o := TMyObject.Create;
  o.Name := 'o1';
  list.Add(o);          // triggering caAdded
  o := TMyObject.Create;
  o.Name := 'o2';
  list.Add(o);          // triggering caAdded
  list[1].Name := 'o3'; // not triggering caChanged
  list.Remove(o);       // triggering caRemoved
  Readln;

end.
4

1 回答 1

2

由或不支持创建TCollections.CreateList的列表。TCollections.CreateObjectListTCollections.CreateInterfaceListINotifyPropertyChanged

您会看到TCollections.CreateObservableList我在示例中使用的限制是仅保存对象,因为这些对象通常是实现属性更改通知的候选对象,因为 PODO 通常不适合用作接口。

您可能仍然可以编写您自己的列表版本,该版本接受接口并查询它们以获取INotifyPropertyChanged.

于 2019-05-21T18:58:13.517 回答