2011-11-14 49 views
0

我一直在爲這個瘋狂的問題奮鬥了幾個小時,並沒有得到任何地方。我在使用TCollection的兩個完全不同的項目中遇到了這個問題。當添加一個新的收集項目時,我需要初始化該項目的值。但是,他們並沒有違約。我甚至將它們設置在兩個完全不同的地方,在項目的構造函數中,以及在集合的add函數中 - 它們都不起作用。一旦項目在那裏,我可以設置值,但我需要設置默認值。我已經做了集合在過去從未有過這個問題,我必須缺少的東西在這裏...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構造,所以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. 
+0

哈!它正在工作!我從來沒有聽說過這種「重新引入」,也沒有聽說過「集合」,但只要它有效,誰在乎。謝謝。 –

+0

只有一個問題:我曾經有一個問題,但將TCollection放入另一個TCollectionItem中。添加GetOwner覆蓋修復了這個問題。我可以期待這些更改在另一個TCollectionItem中有一個TOwnedCollection嗎? –

+1

我使用'reintroduce',因爲您正在更改非虛擬現有方法的簽名,所以您應該隱藏它們,因爲您無法覆蓋它們。至於'TOwnedCollection',它只是自動執行您以前手動執行的操作。你之前在「Owner」指針方面所做的一切都可以正常工作。是的,你必須重寫'GetOwner()'(這是'TOwnedCollection'的作用),以正確地嵌套集合。 –