DinaZen
Catálogo de componentes para montar pantallas de Dinaup: cómo elegir el selector correcto y usar las piezas dinámicas que se pintan solas.
Coges piezas de DinaZen y las encajas en tu pantalla. Hay unas 80 piezas —tarjetas, gráficos, desplegables, diálogos, ventanas…— en una docena de familias, construidas sobre la librería Radzen y pensadas para las apps de Dinaup.
El componente es tonto, los datos mandan: le pasas un dato (o el id de algo que ya existe en Dinaup) y la pieza decide cómo pintarse. A esas las llamamos componentes dinámicos.
Componentes dinámicos: una línea, la cosa entera
Con una sola línea aparece un informe, un formulario o una estadística, generados a partir de los datos. Tres ejemplos en marcha.
1 · Informe DnzReportView
Le das la conexión y el id del informe y pinta la tabla completa: columnas, buscador, filtros y páginas, leídos de la definición del informe. Cambias el id y sale otro informe distinto.
2 · Formulario DnzFormView
Le das la conexión y la sección y monta el formulario entero —cada campo con su tipo y su validación, y el botón de guardar—. Con DatoId="" crea uno nuevo; con un id, edita esa ficha.
3 · Estadística DnzDynamicStat
Le das un dato y él elige cómo mostrarlo: un número suelto → tarjeta KPI; varios → fila de mini-KPIs; una lista → gráfico. No decides el formato, lo decide la forma de los datos.
Y además: ventanas virtuales
Cualquiera de los tres puede salir flotando en una ventana de escritorio (arrastrable, minimizable) con una línea: DnzReportView.OpenAsWindow(WindowManager, client, reportId). Las crea y coloca el DnzWindowManager.
Selectores: la regla de oro
Los desplegables son donde más gente mete la pata. Cinco parecen el mismo, pero la diferencia que importa no es cómo se ven: es de dónde salen los datos. Antes de teclear, una pregunta: ¿este conjunto cabe siempre en memoria y no crece sin tope?
Sí, es acotado
Data y filtras en memoria: RadzenDropDown, DnzEnumDropDown, DnzDropDown o DnzDataGridDropDown según cómo necesites verlo.No, crece sin tope
DnzRowSelector: consulta al servidor paginado, nunca cargas la lista entera. Es el único que deja seleccionar cualquier registro.El error clásico
Tratar datos que crecen sin tope (clientes + proveedores) como si fueran acotados: cargarlos con un Limit 3000 "por si acaso" en un RadzenDropDown. Resultado: el cliente número 3.001 no aparece y no se puede seleccionar, sin ningún aviso. Parece que funciona, hasta que a alguien le falta una ficha.
Árbol de decisión
Tres preguntas y aciertas siempre. Empieza arriba:
Los cinco selectores comparados
| Componente | Datos | Búsqueda | Bindeas… | Pinta | Cuándo |
|---|---|---|---|---|---|
RadzenDropDown | memoria | cliente | un valor (Guid) | 1 texto | lista corta y estable, solo texto |
DnzEnumDropDown | enum | cliente | un enum | 1 texto | cualquier enum (con DisplayName) |
DnzDropDown | memoria | cliente | la fila (objeto) | 1 texto + acciones | lista en memoria con +crear / abrir ficha |
DnzDataGridDropDown | memoria | cliente | la fila (objeto) | N columnas, color, icono | lista en memoria que hay que ver rica |
DnzRowSelector | servidor | servidor (debounce) | la fila o un DefaultID | resultado del informe | dataset ilimitado: cualquier registro |
"Cliente" = filtra en el navegador sobre lo que ya cargaste (instantáneo, pero solo encuentra lo cargado). "Servidor" = cada búsqueda viaja a la API (encuentra TODO, cuesta un viaje de red).
Selectores uno a uno: pros, contras y código
1 · RadzenDropDown
memoria · base Radzen
El de toda la vida. Le das una lista en Data, eliges qué propiedad es el texto y cuál el valor, y devuelve el valor (normalmente un Guid). Filtrado en cliente, opción de virtualizar el render.
| A favor | En contra |
|---|---|
| El más simple y ligero; cero ceremonia. | Carga toda la Data en la RAM del circuito. |
Bindea directo a un Guid / valor. | Si truncas la carga, lo truncado es inseleccionable y sin aviso. |
AllowVirtualization aguanta miles de filas sin lag de DOM. | Una sola "columna": solo texto plano. |
<RadzenDropDown TValue="Guid" @bind-Value=@tipoID Data=@_svc.Tipos TextProperty="TextoPrincipal" ValueProperty="ID" AllowFiltering=true AllowVirtualization=true FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" />2 · DnzEnumDropDown<TEnum>
enum
Un envoltorio sobre RadzenDropDown que se rellena solo a partir de Enum.GetValues. Respeta el [Display(Name="…")] de cada miembro, así que sale el texto bonito en vez del nombre técnico.
| A favor | En contra |
|---|---|
| Cero boilerplate para un enum: no construyes la lista a mano. | Solo sirve para enums. |
Usa el DisplayName automáticamente. | Recalcula los items en cada render (irrelevante: son pocos). |
<DnzEnumDropDown TEnum="EnumRellenadoPoliticaE" @bind-Value=@politica Placeholder="Política…" />3 · DnzDropDown<T>
memoria · IDinaupRow
Como el Radzen pero "Dinaup-aware": trabaja con filas IDinaupRow, muestra el Label y trae de serie los botones de crear (+), quitar (✕) y abrir ficha (↗). Bindea al objeto entero (Selected), no a un Guid.
| A favor | En contra |
|---|---|
| Acciones integradas: crear al vuelo y abrir la ficha. | Sigue siendo en memoria: mismo techo que el Radzen. |
Formato Dinaup sin configurar (usa Label). | Una columna; bindea a objeto (no Guid). |
<DnzDropDown TextProperty="Label" Data=@formasDePago @bind-Selected=@forma OnAdd=@CrearFormaPago />4 · DnzDataGridDropDown<T>
memoria · rico
El hermano vistoso. Misma fuente en memoria, pero el desplegable es una mini-tabla: varias columnas, badges de color (ColorProperty → DnzBadgetAutoColor) e iconos por fila. Para cuando el texto solo no basta para distinguir las opciones.
| A favor | En contra |
|---|---|
| Lo más legible en memoria: columnas, color y estado en la misma fila. | En memoria igual que los anteriores. |
Plantillas propias (Columns, ValueTemplate, IconTemplate). | Más markup; bindea a objeto. |
<DnzDataGridDropDown T="EstadoPedidoRow" TextProperty="Nombre" ColorProperty="Color" @bind-Value=@estado Data=@estados />5 · DnzRowSelector
servidor · ilimitado
El distinto de la familia. No le pasas Data: le pasas un ReportId y el Client de sesión. Abre un popup perezoso y consulta al servidor paginado (20 por tanda) con búsqueda debounced. Da igual que haya 50 o 5 millones de registros: encuentra cualquiera y no llena la RAM.
| A favor | En contra |
|---|---|
| Sin techo: selecciona cualquier registro de la sección. | Cada instancia pesa más en el DOM (form-field + popup). |
| No carga nada en memoria hasta que abres y buscas. | Con DefaultID hace 1 consulta por instancia para resolver el nombre (ver gotcha). |
Filtros avanzados (AdvancedFilter), +crear, abrir ficha, requerido. | Cada búsqueda es un viaje de red (con debounce, pero lo es). |
<DnzRowSelector Client=@SessionPlay Label="Cliente" ReportId=@EntidadesD._SectionID @bind-SelectedRow=@entidad AdvancedFilter=@filtro OnAdd=@CrearCliente />Los detalles finos que cuestan caro
El gotcha del nombre que ahorra la query
En DnzRowSelector hay dos formas de decirle "ya hay algo seleccionado", y eligen entre una consulta o ninguna:
Con DefaultID (un Guid) | Con SelectedRow precargado |
|---|---|
El componente solo tiene el ID, así que para pintar el nombre llama al servidor (SelectByIdAsync → Report_GetAsync) al inicializarse. | Si ya tienes el nombre a mano (p. ej. el movimiento bancario trae mov.Entidad), construyes la fila con Id + Label y se la pasas hecha. |
| 1 query por instancia. En una lista de 50 filas = 50 viajes al servidor solo para pintar lo que ya estaba asignado. | 0 queries al pintar. El servidor solo se toca cuando el usuario abre el buscador de una fila concreta. |
La regla
Si el dato que vas a mostrar ya viaja contigo en memoria, nunca uses DefaultID en una lista: pásale el SelectedRow ya resuelto y te ahorras una consulta por fila. DefaultID solo cuando lo único que tienes es el ID suelto.
Otros tres que muerden
Virtualizar no es paginar
AllowVirtualization=true en RadzenDropDown solo evita pintar 5.000 nodos en el DOM. Los 5.000 objetos siguen en RAM y el cap de carga sigue ahí. Arregla el lag visual, no el problema de memoria ni el de cobertura.
Cargar en memoria es por usuario
En Blazor Server, ese Data grande vive en el circuito de cada usuario conectado. 6.000 entidades × N sesiones = RAM que se multiplica. RowSelector no carga nada hasta que se busca.
Cambiar de familia toca el code-behind
Radzen/Enum bindean a un valor (Guid/enum vía ValueProperty). DnzDropDown / DataGridDropDown / RowSelector bindean al objeto (T/IDinaupRow). Migrar de uno a otro cambia el tipo del binding: el Change=v => SetX(id, v) pasa a SelectedRowChanged. No es solo cambiar la etiqueta.
Checklist de selectores
- ¿Es un enum? →
DnzEnumDropDown. Fin. - ¿El dato crece sin tope (clientes, productos, lotes, empleados…)? →
DnzRowSelector. Es el único que los abarca todos. - ¿Acotado y estable? Entonces según cómo lo veas:
- solo texto →
RadzenDropDown - texto + crear / abrir ficha →
DnzDropDown - columnas / color / icono →
DnzDataGridDropDown
- solo texto →
- Si usas RowSelector en una lista y ya tienes el nombre →
SelectedRowprecargado, nuncaDefaultID.
El resto del catálogo
Las familias que cubren el 90 % de una pantalla. Todas con la misma cara y comportamiento, los estilos vienen resueltos de serie:
Display
DnzSpan* (DnzSpanMoney, DnzSpanDate…).Tarjetas y KPIs
Badges y estados
Inputs y formularios
Diálogos
DinaupFlex y ventanas
Gantt y RRHH
Utilidades
Verlos en vivo
Cada componente tiene su demo y su código en el catálogo de DinaZen. Para conectar tu propia app, mira la guía del SDK .NET y API.