PDA

Ver la Versión Completa : TCOllectionItem con Colecciones no funciona


jorllazo
29-10-2007, 07:15:01
Hola Amigos.
Estoy creando un componente, el cual tiene una propiedad que es TablaMaestra que es del tipo TCollectionItem. A su vez esta TablaMaestra tiene una propiedad "Campos" la cual es uan coleccion de objetos TCampoMaestro que deriva tambien de TCollectionItem, el caso es que cuando estoy viendo las propiedades del componente, e intento acceder a la lista de campos (pulsando en el botoncito de los puntos) este hace caso omiso y no muestra ningun cuadro para añadir los "CampoMaestro" a la coleccion de campos.

Sin eembargo cuando esta Coleccion de "Campos" se la añado al componente directamente que dervia de TComponent el resultado es normal y al pulsar en el botoncilo me muestra el editor correspondiente desde el cual puedo añadir campos a la coleccion.



TCampoMaestro = class (TCollectionItem)
private
m_Nombre: string;
m_Requerido : Boolean;

published

property Nombre : string
read m_Nombre
write m_Nombre;
property Requerido : Boolean
read m_Requerido
write m_Requerido;

end;


TColCamposMaestro = class (TCollection)
public
function getItem(index : integer) : TCampoMaestro;
end;

TTablaMaestra = class (TCollectionItem)
private
m_Nombre: string;
//**************************************
//En este caso es el que no funciona.
m_CamposMaestros : TColCamposMaestro;
procedure SetCamposMaestro(camposMaestro: TColCamposMaestro);
//***************************************
published
property Nombre: string
read m_Nombre
write m_Nombre;
property Campos: TColCamposMaestro
read m_CamposMaestros
write SetCamposMaestro;
public
constructor Create(Collection: TCollectionItem); override;
end;

TComponente = class(TComponent)
private
m_NombreFormulario : string;
m_TablaMaestra: TTablaMaestra;

//********************************************
//Campos de la tabla Maestra En este caso si que funciona
m_CamposMaestro : TColCamposMaestro;
//*********************************************
procedure SetCamposMaestro(camposMaestro: TColCamposMaestro);

public
constructor Create(AOwner: TComponent); override;
destructor Destroy(); override;

published

property NombreFormulario: string
read m_NombreFormulario
write m_NombreFormulario;

property TablaMaestra : TTablaMaestra
read m_TablaMaestra
write m_TablaMaestra;

property CamposMaestro : TColCamposMaestro
read m_CamposMaestro
write SetCamposMaestro;

end;

procedure Register;

implementation
uses Math, SysUtils, StrUtils;

procedure Register;
begin
RegisterComponents('Componentes', [TComponente]);
end;
{TTablaMaestra}
constructor TTablaMaestra.Create(Collection: TCollection);
begin
inherited Create(Collection);
m_CamposMaestros := TColCamposMaestro.Create(TCollectionItem);
m_Nombre := '';
end;
procedure TTablaMaestra.SetCamposMaestro(camposMaestro: TColCamposMaestro);
begin
m_CamposMaestros.Assign(camposMaestro);
end;

{TColCampoMaestro}
function TColCamposMaestro.getItem(Index : integer ) : TCampoMaestro ;
var
elemento : TCampoMaestro;
begin
elemento := nil;
if Items[Index] <> nil Then
elemento := Items[Index] as TCampoMaestro;
Result := elemento;
end;
{TComponenteNT}
constructor TComponente.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
m_CamposMaestro := TColCamposMaestro.Create(TCampoMaestro);
m_TablasDetalle := TColTablasDetalle.Create(TTablaDetalle);
m_TablaMaestra := TTablaMaestra.Create(nil);
//Abrir las tablas necesarias.
end;
destructor TComponente.Destroy();
begin

m_CamposMaestro.Free();
inherited Destroy();

end;
procedure TComponentePlantillaNT.SetCamposMaestro(camposMaestro: TColCamposMaestro);
begin
m_CamposMaestro.Assign(camposMaestro);
end;

end.


Entonces sucede que cuando intento implemetar la coleccion dentro del Objeto derivado de TCollectionItem, este no funciona pero si la creo dentro de en el Objeto derivado de TComponent si que funciona bien. Es que no se puede incluir una coleccion dentro de un item parte de otra ? Que me falta? QUe hago mal?

Gracias

droguerman
29-10-2007, 18:40:02
tienes que hacre override del método getOwner, revisa en el código fuente del DBGrid y los DBColumns para que te guies mejor

jorllazo
30-10-2007, 09:27:33
Hola.. Estoy revisando el codigo como me comentas, y no consigo aclararme del todo, la verdad es que me hago bastante lio.. podrias echarme un cable?

Gracias.

jorllazo
31-10-2007, 16:55:39
HE revisado el codigo de DBGRids... y es justamente (o muy similar en estructura o esencia vamos...) al de arriba. El problema es cuando esa coleccion no es directamente una propiedad de el Objeto TComponent, ahora mismo el problema que tengo es que no me muestra la coleccion en el editor de propiedades. La coleccion la crea, pero cuando le pinchas a los tres puntitos. no aparece el editor correspondiente... Me esta volviendo loco..
alguna ayuda?:confused::confused:

ariefez
31-10-2007, 20:59:23
Guiate de esta unidad tiene lo basico pa crear las colecciones


unit Prueba;

interface

uses
Classes;

type

{ TMiItem }

TMiComponente = class;

TMiItem = class(TCollectionItem)
private
FAlignment: TAlignment;
protected
function GetMiComponente: TMiComponente;
function GetDisplayName: string; override;
public
procedure Assign(Source: TPersistent); override;
property MiComponente: TMiComponente read GetMiComponente;
published
property Alignment: TAlignment read FAlignment write FAlignment default taLeftJustify;
end;

{ TMiLista }

TMiItemClass = class of TMiItem;

TMiLista = class(TCollection)
private
FMiComponente: TMiComponente;
function GetMiItem(Index: Integer): TMiItem;
procedure SetMiItem(Index: Integer; Value: TMiItem);
protected
function GetOwner: TPersistent; override;
procedure Update(Item: TCollectionItem); override;
public
constructor Create(MiComponente: TMiComponente;
InfoListClass: TMiItemClass);
function Add: TMiItem;
property MiComponente: TMiComponente read FMiComponente;
property Items[Index: Integer]: TMiItem read GetMiItem write SetMiItem; default;
end;

TMiComponente = class(TComponent)
private
FMiLista: TMiLista;
procedure SetMiLista(const Value: TMiLista);
protected
function CreateMiLista: TMiLista; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property MiLista: TMiLista read FMiLista write SetMiLista;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Ejemplos', [TMiComponente]);
end;

{ TMiComponente }

constructor TMiComponente.Create(AOwner: TComponent);
begin
inherited;

FMiLista := CreateMiLista;
end;

function TMiComponente.CreateMiLista: TMiLista;
begin
Result := TMiLista.Create(Self, TMiItem);
end;

destructor TMiComponente.Destroy;
begin
FMiLista.Free;

inherited;
end;

procedure TMiComponente.SetMiLista(const Value: TMiLista);
begin
FMiLista := Value;
end;

{ TMiItem }

procedure TMiItem.Assign(Source: TPersistent);
begin
if Source is TMiItem then
begin
if Assigned(Collection) then
Collection.BeginUpdate;
try
FAlignment := TMiItem(Source).Alignment;
finally
if Assigned(Collection) then
Collection.EndUpdate;
end;
end else
inherited Assign(Source);
end;

function TMiItem.GetDisplayName: string;
begin
// Result := 'Nombre q quieras ver en el inspector';
// if Result = '' then
Result := inherited GetDisplayName;
end;

function TMiItem.GetMiComponente: TMiComponente;
begin
if Assigned(Collection) and (Collection is TMiLista) then
Result := TMiLista(Collection).MiComponente
else
Result := nil;
end;

{ TMiLista }

function TMiLista.Add: TMiItem;
begin
Result := TMiItem(inherited Add);
end;

constructor TMiLista.Create(MiComponente: TMiComponente;
InfoListClass: TMiItemClass);
begin
inherited Create(InfoListClass);
FMiComponente := MiComponente;
end;

function TMiLista.GetMiItem(Index: Integer): TMiItem;
begin
Result := TMiItem(inherited Items[Index]);
end;

function TMiLista.GetOwner: TPersistent;
begin
Result := FMiComponente;
end;

procedure TMiLista.SetMiItem(Index: Integer; Value: TMiItem);
begin
Items[Index].Assign(Value);
end;

procedure TMiLista.Update(Item: TCollectionItem);
begin
inherited;

// Actualizacion forma global o por item segun sea "Item"
end;

end.

jorllazo
01-11-2007, 07:46:22
Gracias por tu respuesta.. el caso que es lo que planteaba, hasta aqui me funcionaba bien.. pero el problema es cuando no quiero que la TMiLista sea directamente una propiedad de TMiComponente Si no que necesito que pore ejemplo TMiComponente tenga una propiedad que sea ListaMiItems la cual a su vez tiene la propiedad "Nombre" y una que sea "Items" que sea la que contenga la coleccion ... No se si me explico bien .. que quien deberia derivar en este caso la propiedad ListaMiItems? TPersistent?

Tengo esto :

Componente
-------nombre : string
-------items: Coleccion
---------Item1
---------Item2

Necesito Esto:

Componente
-------nombre : string
-------MiLista :
-----------Nombre : string
-----------Items : coleccion
--------------Item1
--------------Item2
La primera opcion me funciona estupendo, pero esta segunda es a la que me refiero, la cosa esta implementada, pero cuando intento darle el click al boton de la coleccion, no sale el editor.

ariefez
01-11-2007, 19:21:29
ahora veo mas claro lo q quieres hacer te recomiendo leer estos articulos para q logres hacer lo q quieres

aca explica la razon del porque no se muestra
Creating Custom Delphi Components, Part II (http://delphi.about.com/library/bluc/text/uc083101e.htm)


y aca su respectiva solucion: uso de editores
Creating Custom Delphi Components, Part III (http://delphi.about.com/library/bluc/text/uc092501a.htm)

jorllazo
01-11-2007, 21:53:47
Muchas Gracias! Justo esta mañana llegue a leer hasta la Parte II y a medida lo leia me daba cuenta que era lo mismo que me pasaba a mi,pero no encontraba la parte III voy a mirarlo enseguida

Muchiiiisimas gracias por la auyda prestada.

jorllazo
03-11-2007, 06:43:06
Hola..
Continuando con esto se me ocurre a ver si se puede hacer que. Imagnemos que el componente tiene una propiedad Tabla que deriva de TTABLE, y otra propiedad CAMPOS que es una coleccion de TCAMPO.
A su vez TCAMPO tiene una propiedad que es "Field" que deriva de TFIELD

Como puedo hacer para que en el desplegable me salga unicamente los campos contenidos en la propiedad Tabla.Fields? por que ahora mismo si tengo 7 tablas me selecciona los campos de las 7 me gustaria poder filtrar por aquellos que estan en Tabla.Fields

Gacias de nuevo

jorllazo
03-11-2007, 07:35:28
He estado miando y al parecer hay que sobreescribir el metodo GetValues de TClassProperty que es donde se muestran los valores que puede tomar, para ello debo incluir en mi clausula Uses, la Unit DesignEditors pero me lanza un error de compilacion diciendo que no encuentra DesignEditros.dcu, donde puedo obtener este archivo?

Estoy usando la version 7 de delphi.

Gracias

ariefez
04-11-2007, 15:33:00
Si quieres realizar componentes con acceso a datos tienes q trabajar con TDataLink o TFieldLink. Aca hay unos documentos (http://www.i-griegavcl.com/docu.htm) q te ayudaran a elaborar distintos tipos de componentes, espero y te sean de ayuda.