TCollectionItem не инициализирует значения свойств по умолчанию - PullRequest
0 голосов
/ 14 ноября 2011

Я боролся с этой сумасшедшей проблемой в течение нескольких часов и ни к чему не привел. У меня есть эта проблема в двух совершенно разных проектах с использованием TCollection. Когда добавляется новый элемент коллекции, мне нужно инициализировать значения этого элемента. Тем не менее, они не по умолчанию. Я даже устанавливаю их в двух совершенно разных местах, в конструкторе элемента и в функции добавления коллекции - ни один из них не работает. Я могу установить значения, как только элементы появятся, но мне нужно установить значения по умолчанию. Я делал коллекции в прошлом и никогда не сталкивался с этой проблемой, я должен что-то упустить здесь ...

unit JDGrids;

interface

uses
  Classes, Windows, SysUtils, Grids, StrUtils;

type
  TJDGridCol = class;
  TJDGridCols = class;  

  TJDGridCols = class(TCollection)
  private
    fOnEvent: TNotifyEvent;
  private
    fOwner: TComponent;
    procedure DoEvent;
    property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
  protected
    function GetItem(Index: Integer): TJDGridCol;
    procedure SetItem(Index: Integer; Value: TJDGridCol);
    function GetOwner: TPersistent; override;
  public
    constructor Create(AOwner: TComponent);
    destructor Destroy; override;
    function Add: TJDGridCol;
    procedure Assign(Source: TPersistent); override;
    procedure Clear;
    procedure Delete(Index: Integer);
    property Items[Index: Integer]: TJDGridCol read GetItem write SetItem; default;
  end;

  TJDGridCol = class(TCollectionItem)
  private
    fOwner: TComponent;
    fWidth: Integer;
    fTitle: String;
    fCols: TJDGridCols;
    fOnEvent: TNotifyEvent;
    fVisible: Bool;
    procedure SetTitle(const Value: String);
    procedure SetWidth(const Value: Integer);
    procedure DoEvent;
    property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
    procedure SetVisible(const Value: Bool);
  protected
    function GetDisplayName: String; override;
  public
    constructor Create(AOwner: TJDGridCols);
    destructor Destroy; override;
  published
    property Title: String read fTitle write SetTitle;
    property Width: Integer read fWidth write SetWidth;
    property Visible: Bool read fVisible write SetVisible;
  end;

implementation

{ TJDGridCols }

constructor TJDGridCols.Create(AOwner: TComponent);
begin
  inherited Create(TJDGridCol);
  fOwner:= AOwner;
end;

destructor TJDGridCols.Destroy;
begin

  inherited Destroy;
end;

function TJDGridCols.Add: TJDGridCol;
begin
  Result:= TJDGridCol(inherited Add);
  Result.fCols:= Self;
  Result.fTitle:= 'Column '+IntToStr(Result.ID);
  Result.fWidth:= 30;
  Result.fVisible:= True;
  DoEvent;
end;

procedure TJDGridCols.Assign(Source: TPersistent);
begin
  inherited Assign(Source);
  DoEvent;
end;

procedure TJDGridCols.Clear;
begin
  inherited Clear;
  DoEvent;
end;

procedure TJDGridCols.Delete(Index: Integer);
begin
  inherited Delete(Index);
  DoEvent;
end;

function TJDGridCols.GetItem(Index: Integer): TJDGridCol;
begin
  Result:= TJDGridCol(inherited Items[Index]);
end;

function TJDGridCols.GetOwner: TPersistent;
begin
  Result:= fOwner;
end;

procedure TJDGridCols.SetItem(Index: Integer; Value: TJDGridCol);
begin
  inherited Items[Index]:= Value;
  DoEvent;
end;

procedure TJDGridCols.DoEvent;
begin
  if assigned(fOnEvent) then fOnEvent(Self);
end;

{ TJDGridCol }

constructor TJDGridCol.Create(AOwner: TJDGridCols);
begin
  inherited Create(AOwner);
  fOwner:= AOwner.fOwner;
  fCols:= AOwner;
  fTitle:= 'Column '+IntToStr(ID);
  fWidth:= 30;
  fVisible:= True;
end;

destructor TJDGridCol.Destroy;
begin

  inherited Destroy;
end;

procedure TJDGridCol.DoEvent;
begin
  if assigned(fOnEvent) then fOnEvent(Self);
end;

function TJDGridCol.GetDisplayName: String;
begin
  Result:= fTitle;
end;

procedure TJDGridCol.SetTitle(const Value: String);
begin
  fTitle:= Value;
  DoEvent;
end;

procedure TJDGridCol.SetVisible(const Value: Bool);
begin
  fVisible := Value;  
  DoEvent;
end;

procedure TJDGridCol.SetWidth(const Value: Integer);
begin
  fWidth := Value;
  DoEvent;
end;

end.

1 Ответ

2 голосов
/ 14 ноября 2011

Вы не переопределяете конструктор TCollection, поэтому TCollection.Add() не может вызвать ваш конструктор.Вот почему вам нужно было Add() установить значения по умолчанию.

Даже в этом случае вы устанавливаете значения свойств по умолчанию во время построения, но вы не указываете те же значения по умолчанию в декларациях свойств.Это необходимо сделать для правильной работы потоковой передачи DFM.

Вы должны также использовать TOwnedCollection вместо непосредственного использования TCollection.Позвольте TOwnedCollection управлять Владельцем за вас.

Попробуйте это:

unit JDGrids;

interface

uses
  Classes, Windows, SysUtils, Grids, StrUtils;

type
  TJDGridCol = class;

  TJDGridCols = class(TOwnedCollection)
  private
    fOnEvent: TNotifyEvent;
  private
    procedure DoEvent;
    property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
  protected
    function GetItem(Index: Integer): TJDGridCol;
    procedure SetItem(Index: Integer; Value: TJDGridCol);
  public
    constructor Create(AOwner: TComponent); reintroduce;
    destructor Destroy; override;
    function Add: TJDGridCol; reintroduce;
    procedure Assign(Source: TPersistent); override;
    procedure Clear; reintroduce;
    procedure Delete(Index: Integer); reintroduce;
    property Items[Index: Integer]: TJDGridCol read GetItem write SetItem; default;
  end;

  TJDGridCol = class(TCollectionItem)
  private
    fWidth: Integer;
    fTitle: String;
    fOnEvent: TNotifyEvent;
    fVisible: Bool;
    procedure SetTitle(const Value: String);
    procedure SetWidth(const Value: Integer);
    procedure DoEvent;
    procedure SetVisible(const Value: Bool);
    property OnEvent: TNotifyEvent read fOnEvent write fOnEvent;
  protected
    function GetDisplayName: String; override;
    function GetCols: TJDGridCols;
    function GetOwner: TComponent;
  public
    constructor Create(AOwner: TCollection); override;
    destructor Destroy; override;
  published
    property Title: String read fTitle write SetTitle;
    property Width: Integer read fWidth write SetWidth default 30;
    property Visible: Bool read fVisible write SetVisible default True;
  end;

implementation

{ TJDGridCols }

constructor TJDGridCols.Create(AOwner: TComponent);
begin
  inherited Create(AOwner, TJDGridCol);
end;

destructor TJDGridCols.Destroy;
begin
  inherited Destroy;
end;

function TJDGridCols.Add: TJDGridCol;
begin
  Result := TJDGridCol(inherited Add);
  DoEvent;
end;

procedure TJDGridCols.Assign(Source: TPersistent);
begin
  inherited Assign(Source);
  DoEvent;
end;

procedure TJDGridCols.Clear;
begin
  inherited Clear;
  DoEvent;
end;

procedure TJDGridCols.Delete(Index: Integer);
begin
  inherited Delete(Index);
  DoEvent;
end;

function TJDGridCols.GetItem(Index: Integer): TJDGridCol;
begin
  Result:= TJDGridCol(inherited Items[Index]);
end;

procedure TJDGridCols.SetItem(Index: Integer; Value: TJDGridCol);
begin
  inherited SetItems(Index, Value);
  DoEvent;
end;

procedure TJDGridCols.DoEvent;
begin
  if Assigned(fOnEvent) then fOnEvent(Self);
end;

{ TJDGridCol }

constructor TJDGridCol.Create(AOwner: TCollection);
begin
  inherited Create(AOwner);
  fTitle := 'Column ' + IntToStr(ID);
  fWidth := 30;
  fVisible := True;
end;

destructor TJDGridCol.Destroy;
begin
  inherited Destroy;
end;

procedure TJDGridCol.DoEvent;
begin
  if Assigned(fOnEvent) then fOnEvent(Self);
end;

function TJDGridCol.GetDisplayName: String;
begin
  Result := fTitle;
end;

function TJDGridCol.GetCols: TJDGridCols;
begin
  Result := Collection as TJDGridCols;
end;

function TJDGridCol.GetOwner: TComponent;
begin
  Result := GetCols.GetOwner as TComponent;
end;

procedure TJDGridCol.SetTitle(const Value: String);
begin
  if fTitle <> Value then
  begin
    fTitle := Value;
    DoEvent;
  end;
end;

procedure TJDGridCol.SetVisible(const Value: Bool);
begin
  if fVisible <> Value then
  begin
    fVisible := Value;  
    DoEvent;
  end;
end;

procedure TJDGridCol.SetWidth(const Value: Integer);
begin
  if fWidth <> Value then
  begin
    fWidth := Value;
    DoEvent;
  end;
end;

end.
...