asp.net - ejemplo - Control de repetidor-Cancelar enlace para un elemento específico
ejemplo repeater asp net (4)
Dentro de un control de repetidor, ¿hay alguna manera de desvincular ciertos elementos antes de que se muestre la página?
Actualmente, tenemos una colección de artículos vinculados a un repetidor y, si el artículo no forma parte del idioma actual, lo ocultamos.
Quiero poder contar el repetidor y recuperar un número válido. Un recuento que tampoco incluye los elementos ocultos.
¿Es posible ItemDataBound
elementos específicos tal vez en el evento ItemDataBound
?
Actualizar
Para cada elemento de la colección que estamos vinculados, verificamos la base de datos durante el ItemDataBound
para obtener más información sobre el elemento, como el idioma, etc. Esto nos impide filtrar los datos encuadernados antes de vincularlos.
¿Por qué no filtrar el origen de datos antes del enlace? Asumiendo que estás usando algunos objetos personalizados:
myRepeater.DataSource=repository.getItems().Where(item=>item.Language==CurrentLanguage);
Si no los necesitas, no los combines en primer lugar.
Actualizar
Si es posible, debería extraer probatoriamente esa información del DB por adelantado. ¿Son estas listas grandes? Si es así, pulsar el db una vez para cada elemento de la lista aparecerá como un problema de rendimiento.
Estoy de acuerdo con las respuestas de los demás: la mejor solución (tanto para el rendimiento como para la claridad del código) es rediseñar la página para que pueda filtrar las entradas no válidas antes del enlace de datos.
La mayoría de las fuentes de datos no nos permiten eliminar sus elementos mientras ASP.NET los itera. Por ejemplo, si se vincula a una List<T>
genérica simple List<T>
y elimina un elemento mientras lo itera, la lista emitirá una InvalidOperationException
.
En otros casos, ASP.NET realmente itera una copia de la fuente de datos. Si se vincula a una DataTable
, ASP.NET utiliza una copia de los contenidos (la DataView predeterminada) en lugar de iterar las filas de origen por sí mismas: puede eliminar elementos de la fuente de datos subyacente durante la iteración, pero no afecta la operación de enlace de datos .
Si filtrar los elementos de antemano realmente no es una opción, su solución actual está bien: ¡simplemente oculte los artículos! Si necesita obtener el recuento correcto además de eso, realice un seguimiento de la cantidad de elementos no válidos en su controlador ItemDataBound y exhíbalo como una propiedad a nivel de página:
if (IsInvalid(args.Item.DataItem)) {
this.invalidItemCount++;
// code to hide the current item
}
La respuesta es muy sencilla: simplemente establece la propiedad Visible
en false
en el elemento y no se representará. En este ejemplo, estoy eliminando elementos de una lista de productos que solo están disponibles para clientes nuevos si el usuario actual tiene un historial de compras:
void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (!userHasPurchaseHistory) { return; }
// filter out products only allowed for new members
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
System.Data.Common.DbDataRecord rec = (System.Data.Common.DbDataRecord)e.Item.DataItem;
if (rec != null)
{
bool newMemberOnly = Convert.ToBoolean(rec["NewMemberOnly"]);
if (newMemberOnly) { e.Item.Visible = false; }
}
}
}
Tenga en cuenta que lo anterior está vinculado a un IDataReader
, puede que necesite convertir e.Item.DataItem
en un objeto diferente, dependiendo de a lo que se enlace.
Tenga en cuenta también que definitivamente nunca haría otra búsqueda de bases de datos mientras se vincula, nunca debe acceder a la base de datos en un bucle, pero mientras los datos a los que se está vinculando tengan algo que pueda verificar para decidir si desea mostrarlos, no hay nada mal con el filtrado en ItemDataBound
. Podría ser problemático si está haciendo cualquier tipo de paginación, ya que eso haría que los tamaños de página fueran inconsistentes.
Una solución más adecuada podría ser filtrar la colección enlazada si no hay una necesidad específica en esos elementos ocultos. Algo como
items.Where(i => i.IsInLanguage(currentLanguage));
Actualizar:
En cuanto a mí, utilizaría este enfoque:
var items = db.
Where(i => i.IsInLanguage(currentLanguage)).
Where(i => i.SomeField == anotherFilterParameter);
repeater.DataSource = items;
repeater.DataBind();
Entonces, todo el filtrado se aplica de antemano
Esto reducirá el número de viajes de ida y vuelta a la base de datos también, lo que juega para un mejor rendimiento