Los subformularios en modo página pueden mostrar los datos del subregistro actual o todo valor pertinente en función del contexto (variables, imágenes, etc.). Una de las principales ventajas de utilizar subformularios página es que incluyen funcionalidades avanzadas y pueden interactuar directamente con el formulario padre (widgets). Los subformularios página tienen sus propias propiedades y eventos específicos, los cuales puede administrar por programación.
Nota: es posible generar componentes con funcionalidades adicionales vía subformularios. Para mayor información, consulte Desarrollar e instalar componentes 4D.
Para activar el modo página, simplemente deseleccione la opción Subformulario salida en la Lista de propiedades. En este caso, las propiedades relativas a la configuración de los subformularios en lista (Modo de selección, Doble clic en línea, etc.) no se muestran más:
El subformulario en página utiliza el formulario de entrada designado por la propiedad “Formulario detallado”. A diferencia de un subformulario en modo lista, el formulario utilizado puede provenir de la misma tabla que el formulario padre. También es posible utilizar un formulario proyecto. En ejecución, un subformulario página tiene las mismas características de visualización estándar de un formulario de entrada. Los mecanismos de los formularios de salida (relacionados particularmente con la gestión de marcadores) no se activan.
Una variable puede estar asociada a un objeto subformulario. Por defecto, a esta variable no se le da nombre, permitiéndole a su código acceder a ella utilizando un puntero obtenido con el comando OBJECT Get pointer (ver en el manual de Lenguaje).
La variable tiene un tipo (ver la siguiente sección) y puede representarse como una variable estándar en el formulario padre. Su modificación dispara los eventos de formulario y permite sincronizar los valores del formulario padre y del subformulario:
El evento formulario On Data Change permite indicar al contenedor del subformulario que el valor de la variable se modificó en el subformulario.
El evento formulario On bound variable change indica al subformulario (método formulario del subformulario) que la variable se modificó en el formulario padre.
Utilice esta propiedad para definir el tipo de la variable asociada al objeto subformulario. El tipo de variable determina la naturaleza de los valores intercambiados entre el formulario padres y el subformulario a través de esta variable.
Por defecto, se utiliza el tipo Ninguno. Si mantiene este tipo, deberá escribirlo explícitamente a través del código para que la base funcione en modo compilado (ver en el manual Lenguaje).
Si selecciona el tipo Objeto (con un nombre de variable especificado), podrá obtener o definir las propiedades de este objeto dentro del contexto del subformulario utilizando Form (ver Utilizar el objeto asociado al subformulario abajo).
Esta propiedad permite seleccionar diferentes tipos de fuentes:
<Ninguno>: seleccione este tipo de fuente si quiere utilizar un formulario proyecto o un formulario de componente como subformulario. Estos subformularios se utilizan en modo página únicamente: la opción "Subformulario lista" debe deseleccionarse para que funcionen. Para que un formulario de componente aparezca en la lista "Formulario detallado" debe haber sido publicado en el componente (ver el párrafo ).
Nombre de tabla: elija este tipo de fuente si quiere utilizar un formulario de la tabla.
Un objeto subformulario puede tener un método objeto que le permite controlar su funcionamiento, en particular, cuando se desencadenan los eventos. Para obtener una descripción de los eventos administrados por los subformularios en página, consulte la documentación del comando Form event code.
Tenga en cuenta que la interacción entre el contenido del objeto subformulario y el formulario padre debe manejarse a través de mecanismos específicos (ver el párrafo Programación avanzada entre formularios).
La variable asociada al subformulario permite vincular los dos contextos (formulario y subformulario) para dar los toques finales a interfaces sofisticadas. Por ejemplo, imagine un subformulario que representa un reloj dinámico, insertado en un formulario padre que contiene una variable editable de tipo hora:
Ambos objetos (variable hora y contenedor del subformulario) tienen el mismo nombre de variable. En este caso, al abrir el formulario padre, 4D sincroniza ambos valores de forma automática. Si el valor de la variable se define en varios lugares, 4D utiliza el valor que se cargó de último. Se aplica el siguiente orden de carga: 1-Métodos objeto del subformulario 2-Método formulario del subformulario 3-Métodos objeto del formulario padre 4-Método formulario del formulario padre
Cuando se ejecuta el formulario padre, la sincronización de las variables debe ser efectuada por el desarrollador utilizando los eventos formulario adecuados. Dos tipos de interacciones pueden ocurrir: del formulario al subformulario y viceversa.
Caso 1: El valor de la variable del formulario padre se modifica y esta modificación debe repercutir en el subformulario. En nuestro ejemplo, la hora ParisTime pasa a 12:15:00, ya sea porque el usuario introdujo esta hora o porque se actualiza dinámicamente (a través del comando Current time por ejemplo).
En este caso, debe utilizar el evento formulario On bound variable change. Este evento debe seleccionarse en las propiedades del subformulario, se genera en el método de formulario del subformulario.
Se genera el evento de formulario On bound variable change:
Tan pronto como se asigna un valor a la variable del formulario padre, incluso si el mismo valor se reasigna,
Si el subformulario pertenece a la página de formulario actual o la página 0.
Tenga en cuenta que, como en el ejemplo anterior, es preferible utilizar el comando OBJECT Get pointer que devuelve un puntero al contenedor subformulario en lugar de su variable, ya que es posible insertar varios subformularios en el mismo formulario padre (por ejemplo, una ventana que muestra diferentes zonas horarias tiene varios relojes). En este caso, sólo un puntero permite saber qué contenedor de subformulario está en el origen del evento.
Caso 2: El contenido del subformulario se modifica y esta modificación debe pasarse en el formulario padre. En nuestro ejemplo, imagine que la interfaz del subformulario permite al usuario mover "manualmente" las manecillas del reloj.
En este caso, desde el subformulario, debe asignar el valor del objeto a la variable del contenedor del subformulario padre. Como en el ejemplo anterior, le recomendamos que utilice el comando OBJECT Get pointer con el selector Object subform container que devuelve un puntero al contenedor del subformulario.
Asignar el valor de la variable genera el evento formulario On Data Change en el método del objeto contenedor del subformulario padre, lo que permite realizar cualquier tipo de acción. El evento debe seleccionarse en las propiedades del contenedor de subformulario.
Nota: si mueve "manualmente" las manecillas del reloj, esto también genera el evento formulario On Data Change en el método del objeto de la variable valorReloj en el subformulario.
4D asocia automáticamente un objeto (_O_C_OBJECT) a cada subformulario. El contenido de este objeto se puede leer y/o modificar desde el contexto del subformulario, permitiéndole compartir valores en un contexto local.
El objeto se puede crear automáticamente o ser la variable del contenedor principal, si se le asigna un nombre explícito y se escribe como Objeto (ver más adelante). En todos los casos, el objeto es devuelto por el comando Form, que puede llamar directamente al subformulario (utilizar un puntero es inútil). Dado que los objetos siempre se pasan por referencia, si el usuario modifica un valor de propiedad en el subformulario, éste se guardará automáticamente en el propio objeto.
Por ejemplo, en su subformulario, las etiquetas de campo se almacenan en el objeto enlazado para que pueda mostrar diferentes idiomas:
Puede modificar las etiquetas del subformulario asignando valores al objeto InvoiceAddress:
C_OBJECT($lang) $lang:=New object If(<>lang="fr") $lang.CompanyName:="Société :" $lang.LastName:="Nom :" Else $lang.CompanyName:="Company:" $lang.LastName:="Name:" End if
InvoiceAddress.Label:=$lang
Para más información, consulte la descripción del comando Form.
La comunicación entre el formulario padre y las instancias de los subformularios puede requerir ir más allá del intercambio de un valor a través de la variable asociada. De hecho, es posible que desee actualizar las variables en los subformularios en función de las acciones efectuadas en el formulario padre y viceversa. Si usamos el ejemplo anterior del subformulario de tipo "reloj dinámico", podríamos querer definir una o más horas de alarma por cada reloj.
4D ha implementado los siguientes mecanismos para responder a estas necesidades:
Uso del parámetro "subformulario" con el comando OBJECT Get name para especificar el objeto de subformulario y el comando OBJECT Get pointer.
Llamada del objeto contenedor desde el subformulario utilizando el comando CALL SUBFORM CONTAINER,
Ejecución de un método en el contexto del subformulario a través del comando EXECUTE METHOD IN SUBFORM.
Además del selector Object subform container, el comando OBJECT Get pointer acepta un parámetro que indica en qué subformulario buscar el objeto cuyo nombre se especifica en el segundo parámetro. Esta sintaxis sólo puede utilizarse cuando se pasa el selector Object named.
... recupera un puntero a la variable "MiBoton" que se encuentra en el objeto subformulario "MiSubForm". Esta sintaxis permite acceder desde el formulario padre a todo objeto que se encuentra en un subformulario. También tenga en cuenta el comando OBJECT Get name que permite recuperar el nombre del objeto que tiene el foco.
El comando CALL SUBFORM CONTAINER permite a una instancia de subformulario enviar un evento al objeto contenedor del subformulario, el cual puede procesarlo en el contexto del formulario padre. El evento se recibe en el método del objeto contenedor. Puede estar en el origen de cualquier evento detectado por el subformulario (clic, arrastrar y soltar, etc.)
El código del evento es libre (por ejemplo, 20 000 o -100). Puede utilizar un código que corresponde a un evento existente (por ejemplo, 3 para On Validate) o utilizar un código personalizado. En el primer caso, sólo puede utilizar los eventos que ha seleccionado en la lista de propiedades para los contenedores de subformulario. En el segundo caso, el código no debe corresponder a cualquier evento formulario existente. Se recomienda usar un valor negativo para estar seguros de que este código no será utilizado por 4D en futuras versiones.
Para obtener más información, consulte la descripción del comando CALL SUBFORM CONTAINER.
El comando EXECUTE METHOD IN SUBFORM permite a un formulario o a uno de sus objetos solicitar la ejecución de un método en el contexto de la instancia del subformulario, lo que le da acceso a las variables, objetos, etc. del subformulario. Este método también puede recibir parámetros.
Este mecanismo se ilustra en el siguiente diagrama: