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

Estados, monedas, almacenes, tipos propios, un enum. Son decenas y apenas crecen con los años. Lo cargas entero en Data y filtras en memoria: RadzenDropDown, DnzEnumDropDown, DnzDropDown, DnzDataGridDropDown o DnzSectionDropDown, según cómo necesites verlo.

No, crece sin tope

Clientes, proveedores, productos, lotes, empleados. Hoy son 200; dentro de tres años, 8.000. Usa 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

  1. Es un enum: DnzEnumDropDown.
  2. Crece sin tope (clientes, productos, lotes, empleados): DnzRowSelector.
  3. 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
  4. DnzRowSelector en una lista con el nombre ya en memoria: SelectedRow precargado o DefaultLabel, nunca DefaultID solo.

Los selectores comparados

ComponenteDatosBúsquedaEnlaceMuestraCuándo
RadzenDropDownmemoriaclienteun valor (Guid)un textolista corta y estable, solo texto
DnzEnumDropDownenumclienteun enumun textocualquier enum, con [Display(Name)]
DnzDropDownmemoriaclientela fila (T : IDinaupRow)un texto y accioneslista en memoria con crear y abrir ficha
DnzDataGridDropDownmemoriaclientela fila (T : IDinaupRow)columnas, color, iconolista en memoria con columnas, color o icono
DnzSectionDropDownservidor, una cargaclienteun Guidun textosección pequeña y cerrada (hasta MaxItems)
DnzRowSelectorservidor, paginadoservidor, con espera de 500 msla fila (IDinaupRow)resultado del informecatá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ámetroTipoPor defectoPara qué
ValueTEnumValor seleccionado. Úsalo con @bind-Value.
ValueChangedEventCallback<TEnum>Se dispara al cambiar la selección.
Placeholderstring""Texto cuando no hay nada elegido.
DisabledboolfalseBloquea el control.
Stylestring"width:200px"Estilo en línea del desplegable, normalmente el ancho.
Namestring""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ámetroTipoPor defectoPara qué
DataIEnumerable<T>new List<T>()La colección en memoria a elegir.
ValueTFila seleccionada. Úsalo con @bind-Value.
ValueChangedEventCallback<T>Se dispara al cambiar la selección.
TextPropertystringNombre de la propiedad a mostrar. Obligatorio; usa @nameof.
LabelstringEtiqueta del campo.
ColorPropertystringPropiedad con el estilo de color; muestra la opción como etiqueta.
IconoPropertystringPropiedad que aporta el icono de cada opción.
IsRequiredboolfalseMarca visual de obligatorio si no hay valor.
DisabledboolfalseBloquea el control.
Widthstring"280px"Ancho del campo.
StylestringEstilo en línea adicional del campo.
IconstringIcono al inicio del campo.
OpenInWindowbooltrueAbre la ficha del seleccionado en ventana (necesita Client).
ClientDinaupClientCCliente para abrir la ficha en ventana.
OnAddEventCallbackSe dispara al pulsar el botón de añadir cuando no hay nada seleccionado.
OnRemoveEventCallback<T>Se dispara al limpiar. Sin delegado, limpia el valor solo.
OnOpenEventCallback<T>Se dispara al pulsar abrir ficha.
ColumnsRenderFragmentColumnas propias del desplegable.
ValueTemplateRenderFragment<dynamic>Plantilla del valor seleccionado mostrado en el campo.
IconTemplateRenderFragment<T>Plantilla del icono por fila.
ColumnWidthstring""Ancho de columna por defecto del desplegable.
VisiblebooltrueOculta 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ámetroTipoPor defectoPara qué
ClientDinaupClientCCliente contra el que consulta el informe. Obligatorio (EditorRequired).
ReportIdstringGUID del informe (SectionsD.EntidadesD._SectionID) que alimenta la búsqueda.
SelectedRowIDinaupRowFila seleccionada. Úsalo con @bind-SelectedRow.
SelectedRowChangedEventCallback<IDinaupRow>Se dispara al cambiar la selección.
DefaultIDGuidGuid.EmptyID inicial. Sin DefaultLabel, lanza una consulta al informe para resolverlo.
DefaultLabelstringEtiqueta ya conocida para DefaultID: muestra la selección inicial sin consultar.
LabelstringEtiqueta del campo.
PlaceholderstringTexto cuando no hay nada elegido.
IsRequiredboolfalseMarca visual de obligatorio si está vacío.
DisabledboolfalseBloquea el control.
AdvancedFilterList<FilterCondition>Condiciones aplicadas al informe: acotan el universo buscable.
AdminModeboolfalseConsulta el informe en modo administrador.
Widthstring"280px"Ancho del campo.
Stylestring"flex:1"Estilo en línea del campo.
Classstring""Clases CSS extra del contenedor.
IconstringIcono al inicio del campo.
OpenInWindowbooltrueAbre la ficha seleccionada en ventana.
OnAddEventCallback<Guid>Se dispara al pulsar el botón de añadir para crear una ficha nueva.
OnOpenRecordEventCallback<IDinaupRow>Se dispara al pulsar abrir; sin delegado, abre la ficha en ventana.
FetchInterceptorFunc<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ámetroTipoPor defectoPara qué
ClientDinaupClientCObligatorio. Cliente que ejecuta la consulta.
SectionIdstring""Obligatorio. GUID de la sección cuyos registros se listan.
Labelstring""Etiqueta del campo.
ValueGuidGuid.EmptyRegistro seleccionado. Úsalo con @bind-Value.
ValueChangedEventCallback<Guid>Se dispara al cambiar la selección.
DisabledboolfalseBloquea el control.
MaxItemsint500Registros 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ámetroTipoPor defectoPara qué
DataIEnumerable<T>new List<T>()La colección a elegir.
SelectedTFila seleccionada. Úsalo con @bind-Selected.
SelectedChangedEventCallback<T>Se dispara al cambiar la selección.
TextPropertystringPropiedad a mostrar. Obligatorio; usa @nameof.
ColorPropertystringPropiedad de estilo de color de cada opción.
IconoPropertystringPropiedad que aporta el icono de cada opción.
LabelstringEtiqueta del campo.
IconstringIcono al inicio del campo.
StylestringEstilo en línea del control.
ClassstringClases CSS extra.
DisabledboolfalseBloquea el control.
VisiblebooltrueOculta el componente entero.
OnAddEventCallbackSe dispara al pulsar el botón de añadir.
OnRemoveEventCallback<T>Se dispara al limpiar; sin delegado, limpia solo.
OnOpenEventCallback<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ámetroTipoPor defectoPara qué
BounceValueChangedEventCallback<string>Se dispara 500 ms después de que el usuario deja de teclear, con el texto actual.
OnTypingEventCallbackSe dispara en cada tecla, antes de la espera. Para activar un indicador de "buscando" sin esperar.
ValuestringTexto del campo.
Placeholderstring"Buscar..."Texto cuando está vacío.
Classstring""Clases CSS extra para el contenedor.
Stylestring""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ámetroTipoPor defectoPara qué
ClientDinaupClientCCliente contra el que consulta el informe.
ReportIdstringGUID 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.


Relacionado

En esta página