2009-06-26 5 views
5

컬렉션 속성을 사용하여 사용자 지정 구성 요소를 만들려고합니다. 그러나 개체 검사기에서 "..."단추를 클릭하여 디자인 타임에 컬렉션 편집기를 열려고하면 아무 일도 일어나지 않습니다. 내가 누락 된 것?델파이에서 TOwnedCollection 자손 사용하기

TMyCollection = class(TOwnedCollection) 
    private 
    function GetItem(Index: Integer): TMyCollectionItem; 
    procedure SetItem(Index: Integer; const Value: TMyCollectionItem); 
    public 
    function Add : TMyCollectionItem; 
    property Items[Index: Integer]: TMyCollectionItem read GetItem write SetItem; 
    end; 

그리고 항목 : 나는 문제가 무엇인지 모르는 아웃 전체 구현을보고 너무

TMyCollectionItem = class(TCollectionItem) 
    private 
    FValue: integer; 
    protected 
    function GetDisplayName: string; override; 
    public 
    procedure Assign(Source: TPersistent); override; 
    constructor Create(Collection: TCollection); override; 
    destructor Destroy; override; 
    published 
    property Value : integer read FValue write FValue; 
    end; 

답변

12

클래스의 정의가 올바른 모양

여기 내 된 TCollection 자손입니다.

여기 TOwnedCollection, TCollectionItem 및 TComponent를 사용하여 작성한 간단한 단위입니다.

이 장치가 작동하는 것을 알고 있습니다. 코드 검사를위한 기초로 사용하십시오.

Ryan.

unit rmMultiStrings; 

interface 

uses classes, sysutils; 

type 
    ErmMultiStringNameException = Exception; 
    TrmMultiStringsCollection = class; 

    TrmMultiStringCollectionItem = class(TCollectionItem) 
    private 
    fItemDesc: string; 
    fItemName: string; 
    fData : TStringList; 
    fMultiStrings : TrmMultiStringsCollection; 
    function GetStrings: TStringList; 
    function GetStringText: String; 
    procedure SetItemName(const Value: string); 
    procedure SetStrings(const Value: TStringList); 
    procedure SetStringText(const Value: String); 
    public 
    constructor Create(Collection: TCollection); override; 
    destructor Destroy; override; 

    procedure Assign(Source: TPersistent); override; 
    published 
    property ItemName : string read fItemName write SetItemName; 
    property Description : string read fItemDesc write fItemDesc; 
    property Strings : TStringList read GetStrings write SetStrings stored false; 
    property Text : String read GetStringText write SetStringText; 
    end; 

    TrmMultiStringsCollection = class(TOwnedCollection) 
    private 
    function GetItem(AIndex: integer): TrmMultiStringCollectionItem; 
    procedure SetItem(AIndex: integer; const Value: TrmMultiStringCollectionItem); 
    public 

    function Add: TrmMultiStringCollectionItem; 

    function IndexOf(ItemName:string):integer; 
    function ValueOf(ItemName:string):String; 
    function ValueOfIndex(aIndex:integer):string; 

    procedure Assign(Source: TPersistent); override; 

    property Items[AIndex: integer] : TrmMultiStringCollectionItem read GetItem write SetItem; 
    end; 

    TrmMultiStrings = class(TComponent) 
    private 
    fData : TrmMultiStringsCollection; 
    procedure SetData(const Value: TrmMultiStringsCollection); 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 

    function IndexOf(ItemName:string):integer; 
    function ValueOf(ItemName:string):String; 
    function ValueOfIndex(aIndex:integer):string; 
    published 
    property Data : TrmMultiStringsCollection read fData write SetData; 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterClass(TrmMultiStringsCollection); 
    RegisterClass(TrmMultiStringCollectionItem); 
    RegisterComponents('rmConcordia', [TrmMultiStrings]); 
end; 


{ TrmMultiStringCollectionItem } 

procedure TrmMultiStringCollectionItem.Assign(Source: TPersistent); 
var 
    wSrc : TrmMultiStringCollectionItem; 
begin 
    if Source is TrmMultiStringCollectionItem then 
    begin 
    wSrc := TrmMultiStringCollectionItem(Source); 
    ItemName := wSrc.ItemName; 
    Description := wSrc.Description; 
    Text := wSrc.Text; 
    end 
    else 
    inherited; 
end; 

constructor TrmMultiStringCollectionItem.Create(Collection: TCollection); 
begin 
    inherited; 
    fMultiStrings := TrmMultiStringsCollection(Collection); 
    fData := TStringList.create; 
end; 

destructor TrmMultiStringCollectionItem.Destroy; 
begin 
    fData.free; 
    inherited; 
end; 

function TrmMultiStringCollectionItem.GetStrings: TStringList; 
begin 
    result := fData; 
end; 

function TrmMultiStringCollectionItem.GetStringText: String; 
begin 
    result := fData.Text; 
end; 

procedure TrmMultiStringCollectionItem.SetItemName(const Value: string); 
begin 
    if (fItemName <> Value) then 
    begin 
    if fMultiStrings.IndexOf(Value) = -1 then 
     fItemName := Value 
    else 
     raise ErmMultiStringNameException.Create('Item name already exists'); 
    end; 
end; 

procedure TrmMultiStringCollectionItem.SetStrings(
    const Value: TStringList); 
begin 
    fData.Assign(Value); 
end; 

procedure TrmMultiStringCollectionItem.SetStringText(const Value: String); 
begin 
    fData.Text := Value; 
end; 

{ TrmMultiStringsCollection } 

function TrmMultiStringsCollection.Add: TrmMultiStringCollectionItem; 
begin 
    result := TrmMultiStringCollectionItem(inherited Add); 
    result.ItemName := 'Item_'+inttostr(NextID); 
end; 

procedure TrmMultiStringsCollection.Assign(Source: TPersistent); 
var 
    wSrc : TrmMultiStringsCollection; 
    loop : integer; 
begin 
    if (source is TrmMultiStringsCollection) then 
    begin 
    wSrc := TrmMultiStringsCollection(Source); 
    Clear; 
    for loop := 0 to wSrc.Count - 1 do 
     Add.Assign(wSrc.Items[loop]); 
    end 
    else 
    inherited; 
end; 

function TrmMultiStringsCollection.GetItem(
    AIndex: integer): TrmMultiStringCollectionItem; 
begin 
    result := TrmMultiStringCollectionItem(inherited Items[AIndex]); 
end; 

function TrmMultiStringsCollection.IndexOf(ItemName: string): integer; 
var 
    loop : integer; 
begin 
    result := -1; 
    loop := 0; 
    while (result = -1) and (loop < Count) do 
    begin 
     if (CompareText(Items[loop].ItemName, ItemName) = 0) then 
     result := loop 
     else 
     inc(loop); 
    end; 
end; 

procedure TrmMultiStringsCollection.SetItem(AIndex: integer; const Value: TrmMultiStringCollectionItem); 
begin 
    inherited SetItem(AIndex, Value) 
end; 

function TrmMultiStringsCollection.ValueOf(ItemName: string): String; 
begin 
    result := ValueOfIndex(IndexOf(ItemName)); 
end; 

function TrmMultiStringsCollection.ValueOfIndex(aIndex: integer): string; 
begin 
    if (aIndex >= 0) and (aIndex < Count) then 
    result := Items[aIndex].Text 
    else 
    result := ''; 
end; 

{ TrmMultiStrings } 

constructor TrmMultiStrings.Create(AOwner: TComponent); 
begin 
    inherited; 
    fData := TrmMultiStringsCollection.Create(self, TrmMultiStringCollectionItem); 
end; 

destructor TrmMultiStrings.Destroy; 
begin 
    fData.Free; 
    inherited; 
end; 

function TrmMultiStrings.IndexOf(ItemName: string): integer; 
begin 
    result := Data.IndexOf(ItemName); 
end; 

procedure TrmMultiStrings.SetData(const Value: TrmMultiStringsCollection); 
begin 
    fData.Assign(Value); 
end; 

function TrmMultiStrings.ValueOf(ItemName: string): String; 
begin 
    result := Data.ValueOf(ItemName); 
end; 

function TrmMultiStrings.ValueOfIndex(aIndex: integer): string; 
begin 
    result := Data.ValueOfIndex(aIndex); 
end; 

end. 
+2

감사합니다. 오류를 발견하는 데 도움이되었습니다. RegisterClass를 호출하지 않았고 생성자에서 버그가 발생하여 컬렉션의 내부 필드가 0이되었습니다. – Harriv

+0

문제 없으니 기꺼이 도와 드리겠습니다. –