-
пытаюсь создать коллекцию разнородных компонентов. для етого создаю контейнер TCollectionItem в котором помещаю published свойство моего компонента ( published property Filter : BaseEventFilter). саму коллекцию вкладываю в компонент - FiltersSet
при добавлении нового фильтра создаю его с владельцем FiltersSet который содержит коллекцию ( function LogTracks.Add(const template : LogTrackContainer): LogTrackContainer; begin result := add(template.Name, template.Filter.CreateInstance(FiltersSet(Owner)), template.TuneForm); end; ) а как еще? TCollectionItem неможет же быть владельцем TComponent.
на реальном примере использую далекого потомка AdressFilter от базового класса BaseEventFilter
охраняется все кроме того что надо. как быть?
-
собсно часть исходника
type LogTrackContainer = class(TCollectionItem) public FName : string; TuneForm : TFrame; FFilter : BaseEventFilter; //constructor Create(Collection: TCollection); override; destructor Destroy;override; procedure SetDisplayName(const Value: string); override; function GetDisplayName: string; override; protected function GetFilterClass : string; procedure InitFilterClass(const value : string); procedure SetFilter(value : BaseEventFilter); published property Name : string read FName write FName; //property FilterClass : string read GetFilterClass write InitFilterClass; published property Filter : BaseEventFilter read Ffilter write SetFilter; end;
LogTracks = class(TOwnedCollection) private function GetItem(Index: Integer): LogTrackContainer; procedure SetItem(Index: Integer; value : LogTrackContainer); public function Add(const aName : string; aFilter : BaseEventFilter; aTuneForm : TFrame): LogTrackContainer;overload; function Add(const template : LogTrackContainer): LogTrackContainer;overload;
function IndexOf(const aName: string): integer;overload; function Find(const aName: string): LogTrackContainer;overload; function IndexOf(value : TClass): integer;overload; function Find(value : TClass): LogTrackContainer;overload; function IndexOf(value : LogTrackContainer): integer; overload;
function Insert(Index: Integer): LogTrackContainer; property Items[Index: Integer]: LogTrackContainer read GetItem write SetItem; default;
procedure GatterItemsNames(Target : TStrings); end;
FiltersSet = class(TComponent) FItems : LogTracks; procedure AssignItems(value : LogTracks); constructor Create(aOwner : TComponent);override; destructor Destroy;override; published property Items : LogTracks read FItems write AssignItems;
end;
var LogFiltersEnum : LogTracks;
procedure Register;
implementation uses AdressPaleteFrame , sysutils ;
{****************************************************************************** LogTracks *******************************************************************************} function LogTracks.GetItem(Index: Integer): LogTrackContainer; begin result := LogTrackContainer(inherited GetItem(Index)); end;
procedure LogTracks.SetItem(Index: Integer; value : LogTrackContainer); begin inherited SetItem(Index, value); end;
function LogTracks.Insert(Index: Integer): LogTrackContainer; begin result := LogTrackContainer(inherited Insert(Index)); end;
function LogTracks.Add(const aName : string; aFilter : BaseEventFilter; aTuneForm : TFrame): LogTrackContainer; begin result := LogTrackContainer(Add()); result.Filter := aFilter{.CreateInstance}; result.TuneForm := aTuneForm; result.DisplayName := aName; end;
function LogTracks.Add(const template : LogTrackContainer): LogTrackContainer; begin result := add(template.Name, template.Filter.CreateInstance(FiltersSet(Owner)), template.TuneForm); end;
............. ............ ..............
{****************************************************************************** LogTrackContainer *******************************************************************************} procedure LogTrackContainer.SetDisplayName(const Value: string); begin Name := Value; end;
function LogTrackContainer.GetDisplayName: string; begin result := Name; end;
destructor LogTrackContainer.Destroy; begin FreeAndNil(FFilter); inherited; end;
function LogTrackContainer.GetFilterClass : string; var def : LogTrackContainer; begin def := LogFiltersEnum.Find(Filter.ClassType); if assigned(def) then result := def.Name else result := '?'; end;
procedure LogTrackContainer.InitFilterClass(const value : string); var def : LogTrackContainer; begin def := LogFiltersEnum.Find(value); if assigned(def) then begin FreeAndNil(FFilter); TuneForm := nil; if (not assigned(Filter)) then begin FFilter := def.Filter.CreateInstance(FiltersSet(collection.Owner)); TuneForm := def.TuneForm; end; end; end;
procedure LogTrackContainer.SetFilter(value : BaseEventFilter); begin FFilter := value; //FFilter.FreeNotification(Collection.Owner as TComponent); end; {**************************************************************************** FiltersSet ******************************************************************************} constructor FiltersSet.Create(aOwner : TComponent); begin inherited; FItems := LogTracks.Create(Self, LogTrackContainer); end;
destructor FiltersSet.Destroy; begin FreeAndNil(FItems); inherited; end;
procedure FiltersSet.AssignItems(value : LogTracks); begin Fitems.Clear; Fitems.Assign(value); end;
procedure Register; begin RegisterClasses([FiltersSet,LogTracks,LogTrackContainer,AdressFilter]); end;
initialization begin LogFiltersEnum := LogTracks.Create(nil, LogTrackContainer); LogFiltersEnum.Add('AdressFilter', AdressFilter.Create(nil), EditAdressPaleteFrame); end;
finalization begin FreeAndNil(LogFiltersEnum); end;
end.
-
-
если BaseEventFilter унаследовать от TPersistent а не TComponent, то начнуть сохраняться его свойства, но сам он создаваться небудет
-
Для сериализации любых не опубликованных свойств существуют методы TPersistent.DefineProperties и TFiler.DefineProperty
-
Сергей, спасибо за статью. но надежд она мне больших непридала. такое ощущение что чтобы работало надо переписать GetChildren для класса-хозяина-коллекции, и еще приделать fixup свой ко всему етому. оно конешно глобально, и наверно даже полезно, и наверно уже кемто сделано. если у Вас есть чтото похожее киньте сцылко.
а пока я пробую чегото попроще сделать - сохраняю тип фильтра в свойстве, а при загрузке TCollectionItem по етому свойству конструирует мой компонент., если он загружается самый первый, то все его свойства затем загружаются вдогонку.
-
пришел к тому что отказался от колекции вообще, и стал использовать собственный список компонента-коллекции для хранения многихTComponent . все получилось намного проще. тока вот теперь немогу заставить отображаться в object tree view субкомпоненты как ето сделать?
вот текст нового компонента
type
FiltersSet = class(TComponent) protected //FItems : LogTracks; procedure GetChildren(Proc: TGetChildProc; Root: TComponent);override; function GetChildOwner: TComponent; override; function GetItem(index : integer) : baseEventFilter; public function Add(const aName : string; template : BaseEventFilter) : integer;overload; function Add(const aName : string; aFilterClass : EventFilterClass) : integer;overload; procedure GatterItemsNames(target : TStrings);
constructor Create(aOwner : TComponent);override; destructor Destroy;override; property Items[Index : integer] : BaseEventFilter read GetItem; end;
var LogFiltersEnum : FiltersSet;
procedure Register;
implementation uses AdressPaleteFrame , sysutils ;
{**************************************************************************** FiltersSet ******************************************************************************} constructor FiltersSet.Create(aOwner : TComponent); begin inherited; end;
destructor FiltersSet.Destroy; begin inherited; end;
procedure FiltersSet.GetChildren(Proc: TGetChildProc; Root: TComponent); var I: Integer; OwnedComponent: TComponent; begin for I := 0 to ComponentCount - 1 do begin OwnedComponent := Components[I]; if not OwnedComponent.HasParent then Proc(OwnedComponent); end; end;
function FiltersSet.GetChildOwner: TComponent; begin result := self; end;
function FiltersSet.GetItem(index : integer) : BaseEventFilter; begin result := components[index] as BaseEventFilter; end;
function FiltersSet.Add(const aName : string; aFilterClass : EventFilterClass) : integer; var aFilter : baseEventFilter; begin afilter := aFilterClass.Create(Self); aFilter.Name := aName; afilter.SetSubComponent(true); result := afilter.ComponentIndex; end;
function FiltersSet.Add(const aName : string; template : BaseEventFilter) : integer; var aFilter : baseEventFilter; idx : integer; newname : string; namecomp : tcomponent; begin newname := aName; namecomp := FindComponent(aName); if assigned(namecomp) then idx := namecomp.ComponentIndex else idx := -1; while idx >= 0 do begin newname := aName + IntTostr(idx+1); namecomp := FindComponent(newName); if assigned(namecomp) then idx := namecomp.ComponentIndex else idx := -1; end; afilter := template.CreateInstance(Self); aFilter.Name := newName; afilter.SetSubComponent(true); result := afilter.ComponentIndex; end;
procedure FiltersSet.GatterItemsNames(target : TStrings); var idx : integer; begin for idx := 0 to ComponentCount -1 do target.add(components[idx].name); end;
procedure Register; begin RegisterClasses([FiltersSet,AdressFilter]); end;
initialization begin LogFiltersEnum := FiltersSet.Create(nil); LogFiltersEnum.Add('AdressFilter', AdressFilter); end;
finalization begin FreeAndNil(LogFiltersEnum); end;
end.
-
Для того чтобы они отображались в Object Tree View компоненты должны лежать на форме или смотрите в сторону Sprig
-
с етим контейнером вылезла новая трабла - если я создаю inherited форму\фрейм подкомпоненты контейнера немогут найти своих предков при сохранении\загрузке, по той причине что поиск идет по имени компонента в корневой форме а не в контейнере.
подскажите как лечица.
может это вообще ошибка использовать контейнер как собственник своих компонентов? может надо пойти другим путем?
-
может имеет смысл перебазировать свои классы с компонентов на контролы? контрол имеет раздельных owner и parent.
-
уря!. лечение оказалось простым как 2капли:
@@ -52,6 +52,7 @@ constructor FiltersSet.Create(aOwner : TComponent); begin inherited; + SetInline(true); end; destructor FiltersSet.Destroy;
|