2011-11-14 31 views
0

私はこのクレイジーな問題に何時間も挑戦しており、どこにもいません。私はTCollectionを使って2つの全く異なるプロジェクトでこの問題を抱えています。新しいコレクションアイテムが追加されると、そのアイテムの値を初期化する必要があります。しかし、彼らはまったくデフォルトしていません。私は2つの全く異なる場所、アイテムのコンストラクタ、およびコレクションのadd関数にそれらを設定しています。どちらも動作していません。私は項目がそこにあると値を設定することができますが、私はデフォルト値を設定する必要があります。私はこの問題を抱え決して過去のコレクションをやっていないとき、私は...あなたがTCollectionのコンストラクタをオーバーライドしていないTCollectionItemがデフォルトのプロパティ値を初期化していません

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. 

答えて

2

、そうTCollection.Add()はあなたのコンストラクタを呼び出すことはできませんが、ここで何かが欠けている必要があります。そのため、Add()にデフォルト値を設定する必要がありました。

でも、構築中にデフォルトのプロパティ値を設定していますが、プロパティ宣言で同じデフォルト値を指定しているわけではありません。 DFMストリーミングが正しく機能するようにする必要があります。

TCollectionの代わりにTOwnedCollectionも使用する必要があります。 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. 
+0

HA:

はこれを試してみてください!それは働いている!私はこの "再導入"や "TOwnedCollection"について聞いたことは一度もありませんが、それがうまくいく限り誰が気にしますか。ありがとうございました。 –

+0

ちょうど1つの質問:TCollectionを別のTCollectionItem内に置いている間に問題が発生しました。 GetOwnerオーバーライドを追加すると、その問題が修正されました。これらの変更が別のTCollectionItem内にTOwnedCollectionを適切に持つように動作することは期待できますか? –

+1

仮想ではない既存のメソッドのシグネチャを変更しているので 'reintroduce'を使用しました。したがって、それらをオーバーライドできないように非表示にする必要があります。 'TOwnedCollection'に関しては、以前に手動で行っていたことを自動化するだけです。あなたが以前に所有者のポインタに関して持っていたことはうまくいきました。もちろん、コレクションを適切に入れ子にするためには、 'GetOwner()'(これは 'TOwnedCollection'と同じです)をオーバーライドする必要があります。 –

関連する問題