Interfaz de Usuario
Tipos de Pages
Dificultad: 3/10Una Page es el objeto de Business Central que define cómo se ve e interactúa con los datos del sistema. Si las Tablas son el "almacén" de datos, las Pages son las "ventanas" a través de las cuales el usuario final lee, introduce y modifica esa información.
En los ERPs de Microsoft, la interfaz está predefinida por un patrón muy estricto para asegurar
homogeneidad. Dentro del desarrollo usas la propiedad clave PageType para elegir uno de
varios modelos de interfaz que controla cómo se pintarán los datos al usuario.
Estructura base de una Page
page <Id> "<NombreDeLaPage>"
{
PageType = <TipoDePage>;
ApplicationArea = All;
UsageCategory = <Categoría>;
SourceTable = "<NombreTabla>";
layout
{
area(Content)
{
// controles de grupo y de campo
}
area(FactBoxes)
{
// paneles informativos laterales
}
}
actions
{
area(Processing)
{
action(NombreAccion)
{
trigger OnAction()
begin
// lógica del botón
end;
}
}
}
trigger OnOpenPage()
begin
// se ejecuta al abrir la página
end;
}
Propiedades clave de una Page
| Propiedad | Descripción | Ejemplo |
|---|---|---|
PageType |
Define la apariencia y comportamiento de la page | List, Card, ListPart... |
SourceTable |
Tabla de datos que alimenta la page | "Socio" |
ApplicationArea |
Controla qué áreas funcionales pueden ver la page | All |
UsageCategory |
Categoría al buscar con la lupa en BC | Lists, Administration |
CardPageId |
En un List, indica qué Card se abre al hacer clic | "Socio Card" |
Editable |
Si es false, los campos no se pueden modificar |
false |
Caption |
Título visible en la interfaz de BC | 'Gestión de Socios' |
RefreshOnActivate |
Recarga datos al volver a la página | true |
Page Type: List
La vista tipo "Lista". Literalmente pinta una cuadrícula tipo Excel. Está pensada para mostrar muchos registros simultáneos uno bajo el otro, pero habitualmente no se muestran todos los campos de la tabla, solo lo resumido: "Nº", "Título", "Fecha", etc. Los usuarios acceden a List pages para navegar, ordenar y filtrar grandes bases de datos.
- Usa un control
repeateren el layout (repite las filas) - Suele tener
Editable = falsepara evitar ediciones accidentales - Enlaza a la Card correspondiente mediante
CardPageId - Al hacer doble clic en una fila, abre la Card de ese registro
page 50300 "Socio List"
{
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = "Socio";
CardPageId = "Socio Card"; // al hacer clic abre este formulario
Editable = false; // solo lectura desde la lista
layout
{
area(Content)
{
repeater(GroupName) // repite una fila por cada registro
{
field("No."; Rec."No.") { }
field(Nombre; Rec.Nombre) { }
field(Email; Rec.Email) { }
field("Fecha Alta"; Rec."Fecha Alta") { }
field("Total Prestamos"; Rec."Total Prestamos") { } // FlowField
}
}
}
}
Page Type: Card
La vista de "Ficha de Detalle". Ocurre cuando el usuario hace clic en una línea de la List. La Card
solo muestra 1 único registro, pero con un nivel de profundidad masivo. Estructura la
pantalla en paneles llamados FastTabs (grupos como "General", "Facturación", "Envío") donde
acomoda decenas de campos para ese registro concreto.
- Usa controles
grouppara organizar los campos en secciones desplegables - Vinculada desde la List mediante
CardPageId UsageCategory = Administrationpor convención
page 50301 "Socio Card"
{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = "Socio";
layout
{
area(Content)
{
group(General)
{
field("No."; Rec."No.")
{
Importance = Promoted; // aparece destacado aunque el grupo esté cerrado
}
field(Nombre; Rec.Nombre) { Importance = Promoted; }
field(Email; Rec.Email) { }
field("Fecha Alta"; Rec."Fecha Alta") { }
}
group(Direccion)
{
field(Calle; Rec.Calle) { }
field("Codigo Postal"; Rec."Codigo Postal") { }
field(Ciudad; Rec.Ciudad) { }
}
group(Estadisticas)
{
field("Total Prestamos"; Rec."Total Prestamos")
{
Importance = Promoted;
Editable = false; // es un FlowField, no se edita manualmente
}
}
}
}
}
Otros PageTypes
| PageType | Descripción | Control de grupo |
|---|---|---|
ListPlus |
Como List pero con espacio para información adicional debajo. Usado para documentos con cabecera y líneas. | repeater |
ListPart |
Lista embebida dentro de otra page, usada en FactBoxes o subformularios. No lleva
repeater.
|
sin repeater |
CardPart |
Ficha de un único registro embebida en otra page. Usada en FactBoxes para mostrar un resumen. | sin group obligatorio |
RoleCenter |
Página principal tipo "Área de Trabajo" personal con mosaicos, gráficos y alarmas. | cuegroup |
Worksheet |
Similar a List pero concebido para escritura de datos ultra rápida (Diarios Contables). | repeater |
SourceTableView — Pre-filtrar la tabla desde la page
Normalmente una page muestra todos los registros de su SourceTable. Con
SourceTableView puedes aplicar un filtro permanente desde la definición de
la page, de modo que el usuario solo vea un subconjunto concreto de datos. Este filtro es transparente
para el usuario: no lo verá en la barra de filtros.
page 50340 "Prestamos Pendientes List"
{
PageType = List;
ApplicationArea = All;
UsageCategory = Lists;
SourceTable = "Prestamo";
SourceTableView = where(Devuelto = const(false)); // solo préstamos no devueltos
Editable = false;
layout
{
area(Content)
{
repeater(GroupName)
{
field("No."; Rec."No.") { }
field("No. Socio"; Rec."No. Socio") { }
field("No. Libro"; Rec."No. Libro") { }
field("Fecha Prestamo"; Rec."Fecha Prestamo") { }
field("Fecha Devolucion"; Rec."Fecha Devolucion") { }
}
}
}
}
También puedes combinar filtro y ordenación:
// Orden predeterminado además del filtro
SourceTableView = sorting("Fecha Prestamo") order(descending)
where(Devuelto = const(false));
Triggers de Page
Las Pages también tienen triggers que se ejecutan en momentos concretos de la interacción del usuario:
| Trigger | Cuándo se ejecuta |
|---|---|
OnOpenPage() |
Al abrir la page por primera vez |
OnClosePage() |
Al cerrar la page |
OnAfterGetRecord() |
Después de cargar cada registro (útil para cálculos visuales) |
OnNewRecord() |
Al crear un nuevo registro desde la page |
OnQueryClosePage() |
Antes de cerrar, permite preguntar al usuario si desea guardar |
// Mostrar aviso en el título si el socio tiene préstamos pendientes
trigger OnAfterGetRecord()
begin
if Rec."Prestamos Activos" > 0 then
CurrPage.Caption := Rec.Nombre + ' — Préstamos pendientes'
else
CurrPage.Caption := Rec.Nombre;
end;
Tabla comparativa
| List | Card | ListPart | CardPart | |
|---|---|---|---|---|
| ¿Qué muestra? | Varios registros en tabla | Un registro completo | Varios registros (embebido) | Un registro (embebido) |
| Control de grupo | repeater |
group |
sin repeater | sin group obligatorio |
| Uso habitual | Navegar y buscar registros | Crear / editar registros | Historial, sublistas | Resumen de entidad relacionada |
| CardPageId | Recomendado | No aplica | No aplica | No aplica |
| Puede tener FactBoxes | ✅ | ✅ | ❌ | ❌ |
| UsageCategory | Lists |
Administration |
Sin categoría | Sin categoría |
💡 Tips
- Usa siempre
Editable = falseen las List pages para evitar ediciones accidentales. - Vincula siempre la List con su Card mediante
CardPageIdpara que el doble clic funcione correctamente. - En tablas maestras simples (solo código + descripción) puedes prescindir de la Card y editar directamente en la List.
SourceTableViewes ideal para crear vistas especializadas sin duplicar pages: préstamos activos, facturas pendientes, etc.- La propiedad
Importance = Promoteden un campo hace que aparezca visible aunque el grupo esté contraído.