2013-05-29 4 views
7

मैं अपने घटक के लिए एक संपत्ति के रूप में एक कस्टम वर्ग की एक सरणी का उपयोग करने की कोशिश कर रहा हूं, लेकिन समस्या यह है कि मान घटक में सहेजे नहीं गए हैं, जिसका अर्थ है कि अगर मैं सेट करता हूं मूल्यों, सब कुछ बचाने के लिए और फिर प्रोजेक्ट खोलने, मूल्यों के लिए घटक गायब हो जाता है ... मेरी कोड ऐसा दिखाई देता है:एक संपत्ति के रूप में एक कस्टम वर्ग का ऐरे

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. 

मुझे पता है कि यह है कि केवल प्रकाशित गुण स्ट्रीम किया जा सकता है, लेकिन समस्या यह है कि है मेरी संपत्ति एक सरणी है और इसे प्रकाशित नहीं किया जा सकता है ... एक सुझाव है कि मुझे कस्टम स्ट्रीमिंग प्रदान करने के लिए DefineProperties() का उपयोग करना था, लेकिन मुझे नहीं पता कि यह सरणी के साथ कैसे किया जाए। अन्य संभावना है कि मैंने सोचा था कि टीएम क्लास को एक प्रकार की कक्षा में संशोधित करना था कि टीएम कॉम्पोनेंट इसके माता-पिता हो सकता है, जैसे कि यह टीचर्ट में किया जाता है, जिसमें आप श्रृंखला के विभिन्न वर्ग जोड़ सकते हैं। लेकिन मैं नहीं जानता कि क्या वर्ग इस

TMyClass=class(T???????????) 
कि मैं संपत्ति myArray बाहर ले जाना और TMyClass बना सकते हैं और निम्नलिखित के रूप में TMyComponent को जोड़ सकता है के साथ

होना चाहिए:

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

। कौन सा बेहतर विकल्प है? या कोई और बेहतर विचार है?

उत्तर

14

simpliest (और पसंदीदा) हल TMyClass बदलने के लिए TCollectionItem से निकाले जाते हैं और TOwnedCollection को TMyComponent.FMyArray बदलने के लिए है। फिर डीएफएम स्वचालित रूप से आपके लिए आइटम स्ट्रीम करेगा, और आप TMyClass ऑब्जेक्ट्स और उनके गुणों को बनाने और छेड़छाड़ करने के लिए देशी डिज़ाइन-टाइम समर्थन प्राप्त करेंगे।

इस प्रयास करें: [डीसीसी त्रुटि] 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

मैंने इस संस्करण का परीक्षण किया और यह ठीक काम करता है, मुझे बस अपने वास्तविक कोड में परीक्षण करना होगा जो थोड़ा अधिक जटिल है, बहुत बहुत धन्यवाद – Felipe

+0

एक ही चीज़ की तलाश में था। रेमी से महान जवाब, बहुत बहुत धन्यवाद। –

5

मैं DefineProperties के लिए वोट दूंगा! आवश्यक कोड इस प्रकार दिखाई देंगे (सरणी में उदाहरणों में से संभालने से कोई भी नहीं के बराबर है):

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

मैं एक त्रुटि मिली E2362 संरक्षित प्रतीक TReader.ReadProperty और WriteProperties – Felipe

+1

दरअसल के लिए एक ही बात का उपयोग नहीं कर सकते! मैं भूल गया कि मेरे पास एक वर्ग सहायक था जिसने इस काम को किया था। उत्तर अपडेट किया गया। –

+0

फिर भी मेरा लक्ष्य नहीं मिला .. मैं पाठ के रूप में प्रपत्र की जाँच करें और मुझे लगता है कि मिल गया: 'वस्तु MyComponent1: TMyComponent वाम = 160 शीर्ष = 181 चौड़ाई = 185 ऊंचाई = 41 myArray = ( ()) ' – Felipe

संबंधित मुद्दे