2013-05-29 35 views
7

Bileşenimin bir özelliği olarak bir özel sınıf dizisini kullanmaya çalışıyorum, ancak sorun değerlerin bileşene kaydedilmemesi, yani bileşeni kaybolur değerleri, değerleri her şeyi kaydetmek ve tekrar projeyi açmak ... Benim kod aşağıdaki gibi görünür:Özellik olarak bir özel sınıf dizisi

unit Unit1; 

interface 

uses Windows, ExtCtrls,Classes,Controls; 

type 

    TMyClass=class(TPersistent) 
    private 
    FName: string; 
    FValue: double; 
    public 
    property Name: string read FName write FName; 
    property Value: double read FValue write FValue; 
    end; 

    TMyComponent= class(TCustomPanel) 
    private 
    FMyArray: array[0..200] of TMyClass; 

    function GetmyArray(Index: Integer): TMyClass; 

    procedure SetMyArray(index: Integer; Value: TMyClass); 
    public 
    property myArray[index: Integer]: TMyClass read GetMyArray write SetMyArray; 
    end; 

implementation 

function TMyComponent.GetmyArray(Index: Integer): TMyClass; 
begin 
    result:= FmyArray[Index]; 
end; 

procedure TMyComponent.SetMyArray(index: Integer; Value: TMyClass); 
begin 
    FMyArray[index].FName:= Value.FName; 
    FMyArray[index].FValue:= Value.FValue; 
end; 

end. 

sadece yayınlanmış özellikleri akış edilebileceğini biliyoruz ama sorun olduğunu Benim mülk bir dizidir ve yayınlanamaz ...Bir öneri, özel bir akış sağlamak için DefineProperties() kullanmaktı, ancak bunu bir diziyle nasıl yapacağımı göremiyorum. TMyClass'ın bir üst sınıf olabileceğini düşündüğüm başka bir olasılık da, TMyComponent'in kendisi gibi farklı bir sınıf sınıfını ekleyebileceğiniz TChart'da olduğu gibi bir üst sınıfı olabileceğini düşündüm. Ama bu ben mülkiyet BenimDizim çıkarıp TMyClass oluşturun ve aşağıdaki şekilde TMyComponent eklemek verebilecek ile

TMyClass=class(T???????????) 

olmalıdır hangi sınıf bilmiyorum:

MyArray1.parent:= MyComponent1; 
MyArray2.parent:= MyComponent2; 
... 

. Hangisi daha iyi bir seçenek? Yoksa başka bir fikri daha var mı?

cevap

14

simpliest (ve tercih edilen) solüsyonu TCollectionItem türetmek ve TOwnedCollection için TMyComponent.FMyArray değiştirme TMyClass değiştirmektir. Daha sonra DFM sizin için öğeleri otomatik olarak aktaracaktır ve TMyClass nesnelerini ve özelliklerini oluşturmak ve işlemek için yerel tasarım zamanı desteği kazanırsınız.

bu deneyin: [DCC Hatası] MyComponentTest1.pas (155):

unit Unit1; 

interface 

uses 
    Windows, ExtCtrls, Classes, Controls; 

type 
    TMyClass = class(TCollectionItem) 
    private 
    FName: string; 
    FValue: double; 

    procedure SetName(const AValue: string); 
    procedure SetValue(AValue: double); 
    public 
    procedure Assign(ASource: TPersistent); override; 
    published 
    property Name: string read FName write SetName; 
    property Value: double read FValue write SetValue; 
    end; 

    TMyArray = class(TOwnedCollection) 
    private 
    function GetItem(Index: Integer): TMyClass; 
    procedure SetItem(Index: Integer; const Value: TMyClass); 
    public 
    constructor Create(AOwner: TPersistent); 
    function Add: TMyClass; reintroduce; 
    function Insert(Index: Integer): TMyClass; reintroduce; 
    property Items[Index: Integer]: TMyClass read GetItem write SetItem; default; 
    end; 

    TMyComponent = class(TCustomPanel) 
    private 
    FMyArray: TMyArray; 

    procedure SetMyArray(Value: TMyArray); 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
    published 
    property myArray: TMyArray read FMyArray write SetMyArray; 
    end; 

implementation 

procedure TMyClass.Assign(ASource: TPersistent); 
begin 
    if ASource is TMyClass then 
    begin 
    with TMyClass(ASource) do 
    begin 
     Self.FName := Name; 
     Self.FValue := Value; 
    end; 
    Changed(False); 
    end else 
    inherited; 
end; 

procedure TMyClass.SetName(const AValue: string); 
begin 
    if FName <> AValue then 
    begin 
    FName := AValue; 
    Changed(False); 
    end; 
end; 

procedure TMyClass.SetValue(AValue: double); 
begin 
    if FValue <> AValue then 
    begin 
    FValue := AValue; 
    Changed(False); 
    end; 
end; 

constructor TMyArray.Create(AOwner: TPersistent); 
begin 
    inherited Create(AOwner, TMyClass); 
end; 

function TMyArray.GetItem(Index: Integer): TMyClass; 
begin 
    Result := TMyClass(inherited GetItem(Index)); 
end; 

procedure TMyArray.SetItem(Index: Integer; const Value: TMyClass); 
begin 
    inherited SetItem(Index, Value); 
end; 

function TMyArray.Add: TMyClass; 
begin 
    Result := TMyClass(inherited Add); 
end; 

function TMyArray.Insert(Index: Integer): TMyClass; 
begin 
    Result := TMyClass(inherited Insert(Index)); 
end; 

constructor TMyComponent.Create(AOwner: TComponent); 
begin 
    inherited; 
    FMyArray := TMyArray.Create(Self); 
end; 

destructor TMyComponent.Destroy; 
begin 
    FMyArray.Free; 
    inherited; 
end; 

procedure TMyComponent.SetMyArray(Value: TMyArray); 
begin 
    FMyArray.Assign(Value); 
end; 

end. 
+0

Bu sürümü test ettim ve iyi çalışıyor, sadece biraz daha karmaşık olan gerçek kodumu test etmeliyim, çok teşekkürler – Felipe

+0

Aynı şeyi arıyordum. Remy'den harika cevap, çok teşekkür ederim. –

5

DefineProperties için oy veriyorum! gerekli kod aşağıdaki gibi görünebilir (dizideki örnekleri varsayarak hiçbiri nil):

procedure TMyComponent.DefineProperties(Filer: TFiler); 
begin 
    inherited; 
    Filer.DefineProperty('MyArray', ReadMyArray, WriteMyArray, true); 
end; 

procedure TMyComponent.ReadMyArray(Reader: TReader); 
var 
    N: Integer; 
begin 
    N := 0; 
    Reader.ReadListBegin; 
    while not Reader.EndOfList do begin 
    Reader.ReadListBegin; 
    FMyArray[N].Name := Reader.ReadString; 
    FMyArray[N].Value := Reader.ReadFloat; 
    Reader.ReadListEnd; 
    Inc(N); 
    end; 
    Reader.ReadListEnd; 
end; 

procedure TMyComponent.WriteMyArray(Writer: TWriter); 
var 
    I: Integer; 
begin 
    Writer.WriteListBegin; 
    for I := 0 to High(FMyArray) do begin 
    Writer.WriteListBegin; 
    Writer.WriteString(FMyArray[I].Name); 
    Writer.WriteFloat(FMyArray[I].Value); 
    Writer.WriteListEnd; 
    end; 
    Writer.WriteListEnd; 
end; 
+1

bir hata var E2362 korumalı sembolü TReader.ReadProperty Ve Nitekim WriteProperties – Felipe

+1

için aynı şeyi erişilemiyor! Bu işi yapan bir sınıf yardımcım olduğunu unuttum. Cevabı güncellendi. –

+0

Hala amacıma alamadım .. ben metin olarak formunu kontrol edip Anladım: 'nesne MyComponent1: TMyComponent Sol = 160 Üst = 181 Genişliği = 185 Yükseklik = 41 BenimDizi = ( ()) – Felipe

İlgili konular