Interfaz de Usuario
Parts y FactBoxes
Dificultad: 6/10Muchas veces una pantalla principal no es suficiente para describir toda la información. Las Parts son páginas embebidas dentro de otras páginas, y las FactBoxes son paneles informativos que aparecen en la columna derecha de la pantalla. Juntos permiten organizar datos complejos sin confundir al usuario.
El concepto clave: SubPageLink
La propiedad SubPageLink es la clave que hace que una Part muestre solo los datos del
registro seleccionado. Sin ella, el panel mostraría todos los registros de la tabla.
part(NombreLocal; "NombreDeLaPagePart")
{
SubPageLink = "CampoEnTablaHija" = field("CampoEnTablaPadre");
}
FactBoxes — Paneles informativos laterales
Las FactBoxes son paneles que aparecen en la columna derecha de la pantalla cuando el usuario navega por una List o una Card. Su función es mostrar información adicional y contextual del registro seleccionado sin necesidad de abrir otra ventana.
Se definen en el area(FactBoxes) de la page padre. Cada FactBox es un objeto
part que apunta a otra página y se filtra automáticamente al registro seleccionado mediante
SubPageLink.
// En la page "Libro Card": panel lateral con los préstamos de ese libro
layout
{
area(Content)
{
// ... campos principales
}
area(FactBoxes)
{
part(PrestamosLibro; "Prestamo ListPart")
{
// Cada vez que el usuario cambia de libro, el panel se actualiza
SubPageLink = "No. Libro" = field("No.");
}
}
}
ListPart — Historiales o sublistas
Se utiliza cuando la entidad tiene un flujo de diseño tipo Cabecera → Líneas. Piensa en un pedido de venta: abres la cabecera (Card) con los datos globales del cliente, pero esa Card no sirve para listar los 45 artículos comprados. El sistema incrusta un ListPart donde el usuario puede ver el historial completo. Si pasas a tu siguiente factura, el ListPart descarta su filtro en décimas de segundo y muestra el historial del nuevo cliente.
- Muestra varios registros en formato lista dentro del panel
- No usa control
repeater(el propio PageType lo implica) - Ideal para relaciones uno (padre) → muchos (hijos)
page 50311 "Prestamo ListPart"
{
PageType = ListPart;
ApplicationArea = All;
SourceTable = "Prestamo";
layout
{
area(Content)
{
// En un ListPart NO se usa repeater
field("No."; Rec."No.") { }
field("No. Libro"; Rec."No. Libro") { }
field("Fecha Prestamo"; Rec."Fecha Prestamo") { }
field("Fecha Devolucion"; Rec."Fecha Devolucion") { }
field(Devuelto; Rec.Devuelto) { }
}
}
}
⚠️ Diferencia importante con List
En un ListPart el área de contenido NO lleva
repeater. Los registros se muestran como lista automáticamente porque el propio
PageType = ListPart lo implica. En cambio, en una page de tipo List el
repeater es obligatorio.
CardPart — Resúmenes estáticos
Una Card convertida en pieza y enjaulada en un rincón. Sirve para concentrar datos densos pero pequeños de otra tabla, usualmente a la derecha de la pantalla sin ensuciar la Card original. Por ejemplo, en un pedido gigante, el cliente tiene su "Límite de Riesgo" o saldo contable que se asoma a un panel lateral.
- Muestra información de un único registro relacionado
- Para datos de referencia que acompañan al registro principal
- Contenido estático (sin filas repetidas)
page 50310 "Socio Info FactBox"
{
PageType = CardPart;
ApplicationArea = All;
SourceTable = "Socio";
layout
{
area(Content)
{
field("No."; Rec."No.") { }
field(Nombre; Rec.Nombre) { }
field(Email; Rec.Email) { }
field("Total Prestamos"; Rec."Total Prestamos")
{
Editable = false; // FlowField — solo lectura
}
}
}
}
SubPageLink — Conexión con la página padre
La relación entre la page padre y la Part encaja así: el campo de la tabla padre se conecta con el campo de la tabla hija, y BC filtra automáticamente los datos del panel cada vez que el usuario cambia de registro.
// En "Socio Card" (tabla padre: Socio, campo clave: "No.")
area(FactBoxes)
{
part(MisPrestamos; "Prestamo ListPart")
{
// "No. Socio" es el campo en la tabla Prestamo (hija)
// "No." es el campo clave en la tabla Socio (padre)
SubPageLink = "No. Socio" = field("No.");
}
}
// SubPageLink con clave compuesta (varios campos)
SubPageLink = "No. Socio" = field("No."),
"Ejercicio" = field("Ejercicio Fiscal");
ListPart vs CardPart
| ListPart | CardPart | |
|---|---|---|
| ¿Qué muestra? | Varios registros (lista) | Un único registro (ficha) |
| Usa repeater | ❌ No necesario | ❌ No aplica |
| Uso típico | Historial de préstamos, líneas de pedido | Datos de contacto, saldo, límite de riesgo |
| Relación | Uno a muchos (padre → hijos) | Uno a uno (referencia) |
| Puede tener FactBoxes propias | ❌ | ❌ |
Ejemplo completo: Card con FactBox
Una ficha de socio con un ListPart lateral mostrando sus préstamos y un CardPart con su información de contacto:
page 50301 "Socio Card"
{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = "Socio";
layout
{
area(Content)
{
group(General)
{
field("No."; Rec."No.") { Importance = Promoted; }
field(Nombre; Rec.Nombre) { Importance = Promoted; }
field(Email; Rec.Email) { }
}
}
area(FactBoxes)
{
// ListPart: historial de préstamos del socio seleccionado
part(HistorialPrestamos; "Prestamo ListPart")
{
SubPageLink = "No. Socio" = field("No.");
}
// CardPart: resumen de información adicional del socio
part(InfoSocio; "Socio Info FactBox")
{
SubPageLink = "No." = field("No.");
}
}
}
}
💡 Tips
SubPageLinkes obligatorio si quieres que la Part muestre solo los datos del registro seleccionado. Sin él, mostraría todos los registros de la tabla.- Un
ListPartnunca llevarepeater: el propio PageType ya implica que los datos se muestran como lista. - Las Parts (ListPart y CardPart) no pueden tener FactBoxes propias.
- Puedes tener múltiples Parts en el
area(FactBoxes)de una misma page, cada una mostrando información diferente. - Usa
CardPartpara mostrar un resumen rápido sin abrir otra ventana, yListPartpara relaciones uno a muchos.