Selectores
Cómo elegir el desplegable correcto según el origen de los datos: enum, lista en memoria, sección pequeña o catálogo del servidor.
Casi todo lo que el usuario elige en Dinaup pasa por uno de estos componentes. Cinco parecen el mismo desplegable, pero se diferencian en el origen de los datos. Antes de elegir uno, comprueba si el conjunto cabe siempre en memoria o crece sin tope.
Sí, es acotado
Data y filtras en memoria: RadzenDropDown, DnzEnumDropDown, DnzDropDown, DnzDataGridDropDown o DnzSectionDropDown, según cómo necesites verlo.No, crece sin tope
DnzRowSelector: consulta al servidor paginado y nunca carga la lista entera. Es el único que deja seleccionar cualquier registro.Un error frecuente: tratar datos que crecen sin tope (clientes, productos) como acotados y cargarlos con un límite "por si acaso" en un RadzenDropDown. El registro que queda fuera del límite 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
- Es un
enum:DnzEnumDropDown. - Crece sin tope (clientes, productos, lotes, empleados):
DnzRowSelector. - Acotado y estable, según cómo lo veas:
- solo texto, con el valor (
Guid) enlazado:RadzenDropDown - texto, con la fila enlazada y botones de crear, quitar y abrir ficha:
DnzDropDown - columnas, color e icono por fila:
DnzDataGridDropDown - los registros de una sección pequeña, sin cargarlos tú:
DnzSectionDropDown
- solo texto, con el valor (
DnzRowSelectoren una lista con el nombre ya en memoria:SelectedRowprecargado oDefaultLabel, nuncaDefaultIDsolo.
Los selectores comparados
| Componente | Datos | Búsqueda | Enlace | Muestra | Cuándo |
|---|---|---|---|---|---|
RadzenDropDown | memoria | cliente | un valor (Guid) | un texto | lista corta y estable, solo texto |
DnzEnumDropDown | enum | cliente | un enum | un texto | cualquier enum, con [Display(Name)] |
DnzDropDown | memoria | cliente | la fila (T : IDinaupRow) | un texto y acciones | lista en memoria con crear y abrir ficha |
DnzDataGridDropDown | memoria | cliente | la fila (T : IDinaupRow) | columnas, color, icono | lista en memoria con columnas, color o icono |
DnzSectionDropDown | servidor, una carga | cliente | un Guid | un texto | sección pequeña y cerrada (hasta MaxItems) |
DnzRowSelector | servidor, paginado | servidor, con espera de 500 ms | la fila (IDinaupRow) | resultado del informe | catálogo sin tope: cualquier registro |
"Cliente" filtra en el navegador sobre lo cargado: es instantáneo y solo encuentra lo cargado. "Servidor" envía cada búsqueda a la API: encuentra todo y cuesta un viaje de red.
RadzenDropDown con AllowVirtualization=true evita crear miles de nodos en el DOM, pero los objetos siguen en memoria y el límite de carga sigue ahí. Arregla el retraso visual, no la cobertura. Y en Blazor Server, ese Data grande ocupa memoria en el circuito de cada usuario conectado.
Cambiar de familia obliga a cambiar el bloque @code. RadzenDropDown y DnzEnumDropDown enlazan un valor; DnzDropDown, DnzDataGridDropDown y DnzRowSelector enlazan el objeto. Migrar cambia el tipo del enlace y el evento (ValueChanged pasa a SelectedRowChanged).
DnzEnumDropDown
Desplegable directo sobre un enum de C#. No recibe opciones: las obtiene del tipo, y usa el [Display(Name = "...")] de cada valor como texto visible si lo tiene.
<DnzEnumDropDown TEnum="EstadoPedidoE" @bind-Value=@estadoPedido Placeholder="Selecciona estado" />
@code {
EstadoPedidoE estadoPedido = EstadoPedidoE.Pendiente;
}| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Value | TEnum | Valor seleccionado. Úsalo con @bind-Value. | |
ValueChanged | EventCallback<TEnum> | Se dispara al cambiar la selección. | |
Placeholder | string | "" | Texto cuando no hay nada elegido. |
Disabled | bool | false | Bloquea el control. |
Style | string | "width:200px" | Estilo en línea del desplegable, normalmente el ancho. |
Name | string | "" | Nombre del campo (para formularios y validación Radzen). |
Acepta atributos extra que se pasan al elemento raíz.
El texto de cada opción sale de [Display(Name = "Pendiente de pago")] sobre el valor del enum. Sin el atributo, se muestra el nombre técnico del miembro. Añade el atributo en la definición del enum; aquí no hay que cambiar nada.
DnzDataGridDropDown
Selector para una lista en memoria, montado sobre RadzenDropDownDataGrid. Recibe la colección por Data y la propiedad a mostrar con TextProperty, y monta un desplegable con buscador, columnas y acciones (limpiar, abrir ficha, añadir). T tiene que implementar IDinaupRow.
@using static DemoUp.MyDinaup.Reports.FuncionalidadD
<DnzDataGridDropDown T="APIImpuestosC.APIImpuestos_RowC" Label="Impuestos" IsRequired=true TextProperty=@nameof(APIImpuestosC.APIImpuestos_RowC.TextoPrincipal) Data=@impuestos.Values @bind-Value=@impuestoSeleccionado @bind-Value:after=@Recalcular Style="width:100%" />Con color por estado (etiqueta automática) e icono por fila:
<DnzDataGridDropDown T="EstadoPedidoRow" Label="Estado" TextProperty=@nameof(EstadoPedidoRow.Nombre) ColorProperty=@nameof(EstadoPedidoRow.Color) IconoProperty=@nameof(EstadoPedidoRow.Icono) Data=@estados @bind-Value=@estado />| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Data | IEnumerable<T> | new List<T>() | La colección en memoria a elegir. |
Value | T | Fila seleccionada. Úsalo con @bind-Value. | |
ValueChanged | EventCallback<T> | Se dispara al cambiar la selección. | |
TextProperty | string | Nombre de la propiedad a mostrar. Obligatorio; usa @nameof. | |
Label | string | Etiqueta del campo. | |
ColorProperty | string | Propiedad con el estilo de color; muestra la opción como etiqueta. | |
IconoProperty | string | Propiedad que aporta el icono de cada opción. | |
IsRequired | bool | false | Marca visual de obligatorio si no hay valor. |
Disabled | bool | false | Bloquea el control. |
Width | string | "280px" | Ancho del campo. |
Style | string | Estilo en línea adicional del campo. | |
Icon | string | Icono al inicio del campo. | |
OpenInWindow | bool | true | Abre la ficha del seleccionado en ventana (necesita Client). |
Client | DinaupClientC | Cliente para abrir la ficha en ventana. | |
OnAdd | EventCallback | Se dispara al pulsar el botón de añadir cuando no hay nada seleccionado. | |
OnRemove | EventCallback<T> | Se dispara al limpiar. Sin delegado, limpia el valor solo. | |
OnOpen | EventCallback<T> | Se dispara al pulsar abrir ficha. | |
Columns | RenderFragment | Columnas propias del desplegable. | |
ValueTemplate | RenderFragment<dynamic> | Plantilla del valor seleccionado mostrado en el campo. | |
IconTemplate | RenderFragment<T> | Plantilla del icono por fila. | |
ColumnWidth | string | "" | Ancho de columna por defecto del desplegable. |
Visible | bool | true | Oculta el componente entero. |
Acepta atributos extra que se pasan al elemento raíz.
TextProperty es obligatorio. Sin él, el componente muestra un aviso en rojo en vez del desplegable. Pásalo con @nameof(Tipo.Propiedad), nunca como cadena literal.
DnzRowSelector
No recibe Data: recibe un ReportId (el informe de la sección) y un Client, y busca en el servidor de 20 en 20 filas, con una espera de 500 ms tras la última tecla. Para catálogos grandes (clientes, productos, proveedores) donde cargar todo en memoria no tiene sentido.
<DnzRowSelector Client=@Client Label="Cliente" ReportId=@SectionsD.EntidadesD._SectionID @bind-SelectedRow=@cliente AdvancedFilter=@filtro OnAdd=@CrearCliente />Hay tres formas de indicar una selección inicial al cargar; dos no consultan al servidor y una sí:
Si ya tienes la fila (IDinaupRow), pásala por @bind-SelectedRow y el componente la muestra sin consultar al servidor. Con solo el Guid y el nombre, construye una DinaupBasicInformation(id, title), que implementa IDinaupRow.
<DnzRowSelector Client=@Client Label="Cliente" ReportId=@SectionsD.EntidadesD._SectionID @bind-SelectedRow=@cliente />
@code {
private IDinaupRow cliente = new DinaupBasicInformation(mov.EntidadId, mov.Entidad);
}DefaultID con DefaultLabel: muestra la selección inicial sin consultar al servidor y sin notificar SelectedRowChanged.
<DnzRowSelector Client=@Client Label="Cliente" ReportId=@SectionsD.EntidadesD._SectionID DefaultID=@clienteId DefaultLabel=@clienteNombre @bind-SelectedRow=@cliente />Con DefaultID solo, el componente consulta el informe (SelectByIdAsync) para resolver la fila y mostrar su etiqueta. Una consulta por instancia: en una lista de 50 filas son 50 viajes al servidor solo para mostrar lo que ya estaba asignado.
<DnzRowSelector Client=@Client Label="Cliente" ReportId=@SectionsD.EntidadesD._SectionID DefaultID=@clienteId @bind-SelectedRow=@cliente />Si ya tienes el nombre en memoria, no uses DefaultID solo en una lista: pasa la fila o DefaultLabel y ahorras una consulta por fila. Usa DefaultID solo cuando lo único que tienes es el ID.
| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Client | DinaupClientC | Cliente contra el que consulta el informe. Obligatorio (EditorRequired). | |
ReportId | string | GUID del informe (SectionsD.EntidadesD._SectionID) que alimenta la búsqueda. | |
SelectedRow | IDinaupRow | Fila seleccionada. Úsalo con @bind-SelectedRow. | |
SelectedRowChanged | EventCallback<IDinaupRow> | Se dispara al cambiar la selección. | |
DefaultID | Guid | Guid.Empty | ID inicial. Sin DefaultLabel, lanza una consulta al informe para resolverlo. |
DefaultLabel | string | Etiqueta ya conocida para DefaultID: muestra la selección inicial sin consultar. | |
Label | string | Etiqueta del campo. | |
Placeholder | string | Texto cuando no hay nada elegido. | |
IsRequired | bool | false | Marca visual de obligatorio si está vacío. |
Disabled | bool | false | Bloquea el control. |
AdvancedFilter | List<FilterCondition> | Condiciones aplicadas al informe: acotan el universo buscable. | |
AdminMode | bool | false | Consulta el informe en modo administrador. |
Width | string | "280px" | Ancho del campo. |
Style | string | "flex:1" | Estilo en línea del campo. |
Class | string | "" | Clases CSS extra del contenedor. |
Icon | string | Icono al inicio del campo. | |
OpenInWindow | bool | true | Abre la ficha seleccionada en ventana. |
OnAdd | EventCallback<Guid> | Se dispara al pulsar el botón de añadir para crear una ficha nueva. | |
OnOpenRecord | EventCallback<IDinaupRow> | Se dispara al pulsar abrir; sin delegado, abre la ficha en ventana. | |
FetchInterceptor | Func<string, bool, Func<Task<ReportResponse>>, Task<ReportResponse>> | Gancho de caché del DnzReportView interno: reabrir el desplegable sin cambios sirve la primera página desde caché. |
Acepta atributos extra que se pasan al elemento raíz.
AdvancedFilter acota la búsqueda: con un List<FilterCondition> el usuario solo busca dentro de ese subconjunto (clientes activos, productos de un almacén). Combínalo con OnAdd para que el usuario cree el registro si no encuentra lo que busca. FilterCondition se construye con new FilterCondition(field, operator, value).
Métodos públicos por @ref: SelectByIdAsync(Guid id) resuelve la fila contra el informe; SelectAsync(...) acepta una IDinaupRow, una DinaupBasicInformation u otro DnzRowSelector como origen; ToggleAsync() abre o cierra el desplegable.
DnzSectionDropDown
Desplegable con los registros de una sección, cargados una vez con Client.IAQuery_GetAsync(new IAQueryRequestParameters(sectionId, MaxItems)). Para secciones pequeñas y cerradas (estados, tipos, categorías) donde el usuario espera abrir y elegir. Enlaza el Guid del registro. El filtro busca entre lo cargado; si la sección tiene más registros que MaxItems, avisa de que solo se muestran los primeros.
<DnzSectionDropDown Client=@Client SectionId=@SectionsD.ImpuestosD._SectionID Label="Impuesto" @bind-Value=@impuestoId />
@code {
private Guid impuestoId;
}| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Client | DinaupClientC | Obligatorio. Cliente que ejecuta la consulta. | |
SectionId | string | "" | Obligatorio. GUID de la sección cuyos registros se listan. |
Label | string | "" | Etiqueta del campo. |
Value | Guid | Guid.Empty | Registro seleccionado. Úsalo con @bind-Value. |
ValueChanged | EventCallback<Guid> | Se dispara al cambiar la selección. | |
Disabled | bool | false | Bloquea el control. |
MaxItems | int | 500 | Registros que trae la consulta. Por encima, el resto no aparece. |
DnzDropDown
El mismo desplegable sobre IDinaupRow que DnzDataGridDropDown, sin columnas, plantillas ni apertura de ficha en ventana. Enlaza la fila con @bind-Selected y trae los botones de crear, quitar y abrir ficha. TextProperty es obligatorio.
@using static DemoUp.MyDinaup.Reports.FuncionalidadD
<DnzDropDown T="APIAlmacenesC.APIAlmacenes_RowC" Label="Almacén" TextProperty=@nameof(APIAlmacenesC.APIAlmacenes_RowC.TextoPrincipal) Data=@almacenes.Values @bind-Selected=@almacenSeleccionado />| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Data | IEnumerable<T> | new List<T>() | La colección a elegir. |
Selected | T | Fila seleccionada. Úsalo con @bind-Selected. | |
SelectedChanged | EventCallback<T> | Se dispara al cambiar la selección. | |
TextProperty | string | Propiedad a mostrar. Obligatorio; usa @nameof. | |
ColorProperty | string | Propiedad de estilo de color de cada opción. | |
IconoProperty | string | Propiedad que aporta el icono de cada opción. | |
Label | string | Etiqueta del campo. | |
Icon | string | Icono al inicio del campo. | |
Style | string | Estilo en línea del control. | |
Class | string | Clases CSS extra. | |
Disabled | bool | false | Bloquea el control. |
Visible | bool | true | Oculta el componente entero. |
OnAdd | EventCallback | Se dispara al pulsar el botón de añadir. | |
OnRemove | EventCallback<T> | Se dispara al limpiar; sin delegado, limpia solo. | |
OnOpen | EventCallback<T> | Se dispara al pulsar abrir ficha. |
Acepta atributos extra que se pasan al elemento raíz.
DnzSearchInput
Caja de búsqueda con icono de lupa que espera 500 ms tras la última tecla (Dinaup.Debouncer). No es un selector: es la pieza que dispara el filtro sin lanzar una consulta por cada tecla. La usa DnzRowSelector internamente, y sirve para tu propio buscador sobre una lista o un informe.
<DnzSearchInput Placeholder="Buscar producto" BounceValueChanged=@OnBuscar Class="w-100" />
@code {
async Task OnBuscar(string texto)
{
await CargarResultados(texto);
}
}| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
BounceValueChanged | EventCallback<string> | Se dispara 500 ms después de que el usuario deja de teclear, con el texto actual. | |
OnTyping | EventCallback | Se dispara en cada tecla, antes de la espera. Para activar un indicador de "buscando" sin esperar. | |
Value | string | Texto del campo. | |
Placeholder | string | "Buscar..." | Texto cuando está vacío. |
Class | string | "" | Clases CSS extra para el contenedor. |
Style | string | "" | Estilo en línea del contenedor. |
Los atributos extra (autofocus, maxlength) van al <input>.
DnzItemPickerDialog
Ventana de selección sobre un informe, en lugar de un desplegable embebido. Se abre con OpenAsync y devuelve la fila elegida, o null si el usuario cierra.
@inject DialogService DialogService
@code {
async Task ElegirCliente()
{
var fila = await DnzItemPickerDialog.OpenAsync(DialogService, Client, SectionsD.EntidadesD._SectionID);
if (fila.IsNotNull()) clienteSeleccionado = fila;
}
}| Parámetro | Tipo | Por defecto | Para qué |
|---|---|---|---|
Client | DinaupClientC | Cliente contra el que consulta el informe. | |
ReportId | string | GUID del informe que se muestra en el diálogo. |
El método estático OpenAsync(DialogService, DinaupClientC, string reportId) abre el diálogo (ancho min(95%, 1806px), alto 600 px, redimensionable y arrastrable) con un DnzReportView de 50 filas por página y devuelve un DinaupDynamicRowDTO, o null si se cancela.
Para elegir una ficha dentro de un formulario, casi siempre conviene DnzRowSelector embebido. Reserva este diálogo para cuando la selección es una acción aparte (un botón Elegir cliente que abre la ventana) y no un campo más del formulario.