Форум: "Компоненты";
Текущий архив: 2006.02.12;
Скачать: [xml.tar.bz2];
ВнизСохранение поля типа TObjectList Найти похожие ветки
← →
Andrushk (2005-08-17 15:07) [0]Господа, подскажите плиз как написать сохранение поля типа TObjectList компонента.
Нашел подобный вопрос: http://delphimaster.net/view/5-1123089950/
-но здесь посоветовали воспользоваться TColection.
Первый раз возникает необходимость сохранить сложное свойство, не соображу как правильнее и оптимальней воспользоваться Filer.DefineBinaryProperty/Filer.DefineProperty.
TObjectList ссылается на объекты типа:
TFilterOneField = class
FName: string;
FType: integer;
isUse: boolean;
VisibleFName: string;
DataSetField: string;
QueryNames: string;
ReferenceForm: TForm;
ReferenceFieldName: string;
...
end;
← →
Юрий Зотов © (2005-08-17 20:13) [1]Вам принципиально важно, чтобы это был именно TObjectList? Если да, то что-то вроде этого (в работе не проверял, только компилировал!):
unit YzSavedObjectList;
interface
uses
Classes, Contnrs, Forms;
type
TYzSavedObject = class
private
procedure ReadSelf(Reader: TReader);
procedure WriteSelf(Writer: TWriter);
public
Str: string;
Int: integer;
Form: TForm;
end;
TYzSavedObjectListContainer = class(TComponent)
private
FList: TObjectList;
procedure ReadList(Reader: TReader);
procedure WriteList(Writer: TWriter);
protected
procedure DefineProperties(Filer: TFiler); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property List: TObjectList read FList;
end;
implementation
{ TYzSavedObject }
procedure TYzSavedObject.ReadSelf(Reader: TReader);
begin
with Reader do
begin
ReadListBegin;
Str := ReadString;
Int := ReadInteger;
if ReadBoolean then
Form := ReadRootComponent(nil) as TForm
else
Form := nil;
ReadListEnd
end
end;
procedure TYzSavedObject.WriteSelf(Writer: TWriter);
begin
with Writer do
begin
WriteListBegin;
WriteString(Str);
WriteInteger(Int);
if Assigned(Form) then
begin
WriteBoolean(True);
WriteRootComponent(Form)
end
else
WriteBoolean(False);
WriteListEnd
end;
end;
{ TYzSavedObjectListContainer }
constructor TYzSavedObjectListContainer.Create(AOwner: TComponent);
begin
inherited;
FList := TObjectList.Create
end;
procedure TYzSavedObjectListContainer.DefineProperties(Filer: TFiler);
function IsListSaved: boolean;
begin
Result := (Filer.Ancestor = nil) and (FList.Count > 0)
end;
begin
inherited;
Filer.DefineProperty("YzSavedObjects", ReadList, WriteList, IsListSaved)
end;
destructor TYzSavedObjectListContainer.Destroy;
begin
FList.Free;
inherited
end;
procedure TYzSavedObjectListContainer.ReadList(Reader: TReader);
begin
Reader.ReadListBegin;
FList.Clear;
while not Reader.EndOfList do
TYzSavedObject(FList.Items[FList.Add(TYzSavedObject.Create)]).ReadSelf(Reader);
Reader.ReadListEnd
end;
procedure TYzSavedObjectListContainer.WriteList(Writer: TWriter);
var
i: integer;
begin
Writer.WriteListBegin;
for i := 0 to FList.Count - 1 do
TYzSavedObject(FList.Items[i]).WriteSelf(Writer);
Writer.WriteListEnd
end;
end.
А если принципиальной разницы нет, то будет гораздо проще наследовать TFilterOneField от TCollectionItem, а вместо TObjectList использовать TOwnedCollection. Дело в том, что для коллекций TReader и TWriter имеют уже готовые ReadCollection и WriteCollection, а если коллекцию вынести в published, то и вообще ничего не потребуется, все будет сохраняться и читаться автоматически (к тому же, Вы сможете редактировать элементы коллекции прямо в Object Inspector).
← →
Andrushk (2005-08-18 11:36) [2]Большое спасибо, в очередной раз убеждаюсь что все гениальное просто:-)
Открыл для себя, что в DefineProperty имя параметра не может совпадать с именем свойства...возможно я баклан и это всем известный факт :-). У меня вчера с этим проблемы были - компонет сохраняется, а на загрузку непонятные ошибки лезут. И сегодня тоже самое было, пока не стал сравнивать чем мой код от Вашего отличается.
Вобщем спасибо!
← →
Юрий Зотов © (2005-08-18 14:28) [3]> Andrushk (18.08.05 11:36) [2]
> DefineProperty имя параметра не может совпадать с именем
> свойства
Точно так. Может совпадать, но совершенно не обязано. Даже более того - этот параметр ни к каким свойствам вообще не имеет никакого отношения. DefineProperties просто определяет способ сохранения и загрузки некоего параметра с произвольным именм, которое хранится в DFM. А уж что это за параметр, где и как он используется - среде все это глубоко по барабану (например, TComponent свои Left и Top упаковывает и хранит в DesignInfo).
> ...возможно я баклан
Судя по этой ветке - вряд ли...
:о)
> и это всем известный факт
Далеко не всем. Но грамотные разработчики компонентов знать об этом все же должны.
> У меня вчера с этим проблемы были - компонет сохраняется, а
> на загрузку непонятные ошибки лезут. И сегодня тоже самое
> было, пока не стал сравнивать
Если published-свойство хранится через DefineProperties, то в самом объявлении свойства обычно указывают stored False - чтобы избежать повторного сохранения. Судя по описанной проблеме, не исключено, что Вам стоит поступить так же.
← →
Andrushk (2005-08-18 15:19) [4]Странно, но stored False не помогло...
Как только имя published-свойства совпадает с именем параметра в DefineProperties при загрузке параметров компонента возникает ошибка...а сохраняется нормально.
← →
Юрий Зотов © (2005-08-18 17:41) [5]> Странно, но stored False не помогло...
Похоже, просто остался старый DFM, где свойство было уже раньше записано. Пакету сделайте Build (не Compile), а DFM подчистите Блокнотом.
← →
Наиль © (2005-08-18 21:21) [6]А зачем блокнотом? Есть же Alt+F12.
Лучше почистить, а потом Build.
← →
Наиль © (2005-08-18 21:28) [7]>[1]
Большое спасибо за DefineProperties. В своё время, была в нём необходимость, удалось обойтись без него. Но стандартные методы всегда лучше.
← →
Юрий Зотов © (2005-08-18 21:29) [8]> Наиль © (18.08.05 21:21) [6]
Если чистить DFM в среде с еще неперебилденным пакетом, то не исключено, что при переходе просмотра обратно в форму среда все запишет в DFM снова.
← →
Andrushk (2005-08-19 09:38) [9]Либо у меня руки не от туда растут либо что-то не так:-))
published
...
property FilterFields: TFilterFields read FFieldsList write FFieldsList stored false;
...
inherited DefineProperties(Filer);
Filer.DefineProperty("FilterFields",ReadList,WriteList,IsListSaved);
...
нормально сохраняется, смотрел dfm-ку, но читаться не хочет, а стоит написать "FiltFields" - все становиться нормально, даже прямо в dfm-ке подправляешь и она нормально грузится...
может stored только на сохранение действует?
из хелпа:
If a property has no stored directive, it is treated as if stored True were specified.
...
...and the stored specifier is True, then the property"s value is saved. Otherwise, the property"s value is not saved.
а про чтение ничего не сказано, только запись.
← →
Наиль © (2005-08-19 22:19) [10]Написал длиное-длиное сообщение о том, что как и почему. И всё потерялось при не удачной передаче сообщения в форум. Поэтому в двух словах:
Проанализируй строчки, 6371-6372, 6385-6393 в модуле Classes. Особено обрати внимание наif PropInfo <> nil
. Если добъешься, что GetPropInfo для заданого свойства возвращает nil, то получишь то, что хотел.
Для того, чтобы этого добиться проанализируй строчки от 887 в модуле TypInfo. Напомню переход на нужную строчку Alt+G. Для перехода в модуль Classes пишешь Classes и нажимаешь Ctrl+Enter.
Удачи.
← →
Andrushk (2005-08-22 09:13) [11]> Наиль © (19.08.05 22:19) [10]
Спасибо, попробую.
Страницы: 1 вся ветка
Форум: "Компоненты";
Текущий архив: 2006.02.12;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.038 c