为什么在对象更改时不触发 Spring4D 的 IList<T> OnChanged 事件(而添加和删除触发事件)?

Why is Spring4D's IList<T> OnChanged event not fired when the object changes (while Add and Remove fire the event)?

我修改了来自 的 @Stefan Glienkes 示例以使用 IList,因为我在我的列表中使用了接口对象。 在事件处理程序中,我可以处理 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.

TCollections.CreateListTCollections.CreateObjectListTCollections.CreateInterfaceList 创建的列表不支持 INotifyPropertyChanged

你看到我在我的示例中使用的 TCollections.CreateObservableList 与仅保存对象相矛盾,因为这些对象通常是实施 属性 更改通知的候选者,因为 PODO 通常不适合用作接口。

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