Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial se describen ejemplos de cómo se da formato a la apariencia de los controles DataList y Repeater, ya sea mediante funciones de formato dentro de plantillas o controlando el evento DataBound.
Introducción
Como vimos en el tutorial anterior, DataList ofrece una serie de propiedades relacionadas con el estilo que afectan a su apariencia. En concreto, vimos cómo asignar clases CSS predeterminadas a las propiedades DataList s HeaderStyle
, ItemStyle
, AlternatingItemStyle
y SelectedItemStyle
. Además de estas cuatro propiedades, DataList incluye una serie de otras propiedades relacionadas con el estilo, como Font
, ForeColor
, BackColor
y BorderWidth
, por nombrar algunas. El control Repeater no contiene ninguna propiedad relacionada con el estilo. Cualquier configuración de estilo de este tipo debe realizarse directamente dentro del marcado en las plantillas del repetidor.
Sin embargo, a menudo, el formato de los datos depende de los propios datos. Por ejemplo, al enumerar productos, es posible que deseemos mostrar la información del producto en un color de fuente gris claro si se interrumpe, o es posible que deseemos resaltar el UnitsInStock
valor si es cero. Como vimos en los tutoriales anteriores, GridView, DetailsView y FormView ofrecen dos formas distintas de dar formato a su apariencia en función de sus datos:
-
El
DataBound
evento crea un controlador de eventos para el evento adecuadoDataBound
, que se desencadena después de que los datos se hayan enlazado a cada elemento (para gridView era elRowDataBound
evento; para DataList y Repeater es elItemDataBound
evento). En ese controlador de eventos, los datos que acaban de enlazarse se pueden examinar y tomar decisiones de formato. Hemos examinado esta técnica en el tutorial Formato personalizado basado en datos . - Funciones de formato en plantillas al usar TemplateFields en los controles DetailsView o GridView, o una plantilla en el control FormView, podemos agregar una función de formato a la clase de código subyacente de la página ASP.NET, la capa lógica de negocios o cualquier otra biblioteca de clases accesible desde la aplicación web. Esta función de formato puede aceptar un número arbitrario de parámetros de entrada, pero debe devolver el CÓDIGO HTML para representarlo en la plantilla. Las funciones de formato se examinaron por primera vez en el tutorial Uso de TemplateFields en el Control GridView.
Ambas técnicas de formato están disponibles con los controles DataList y Repeater. En este tutorial se describen ejemplos que usan ambas técnicas para ambos controles.
Uso delItemDataBound
controlador de eventos
Cuando los datos se enlazan a un DataList, ya sea desde un control de origen de datos o asignando los datos mediante programación a la propiedad del control y llamando a su método DataSource
, se desencadena el evento DataBind()
, se enumera el origen de datos y cada registro de datos se enlaza al DataList. Para cada registro del origen de datos, DataList crea un DataListItem
objeto que se enlaza al registro actual. Durante este proceso, DataList genera dos eventos:
-
ItemCreated
se desencadena una vezDataListItem
ha sido creado -
ItemDataBound
se activa después de que el registro actual se haya enlazado alDataListItem
En los pasos siguientes se describe el proceso de enlace de datos para el control DataList.
Se desencadena el evento DataList.
DataBinding
Los datos se enlazan a DataList.
Para cada registro del origen de datos
- Cree un objeto
DataListItem
- Desencadenar el
ItemCreated
evento - Vincule el registro a
DataListItem
- Desencadenar el
ItemDataBound
evento - Añade
DataListItem
a la colecciónItems
- Cree un objeto
Al enlazar datos al control Repeater, avanza a través de la misma secuencia exacta de pasos. La única diferencia es que en lugar de que se creen instancias de DataListItem
, el Repeater usa RepeaterItem
s.
Nota:
Es posible que el lector astuto haya observado una ligera anomalía entre la secuencia de pasos que transcurren cuando DataList y Repeater están enlazados a datos en comparación con cuando GridView está enlazado a datos. Al final del proceso de enlace de datos, GridView genera el DataBound
evento; sin embargo, ni el control DataList ni Repeater tienen este evento. Esto se debe a que los controles DataList y Repeater fueron creados durante la época de ASP.NET 1.x, antes de que el patrón de manejo de eventos previo y posterior se volviera común.
Al igual que con GridView, una opción para dar formato en función de los datos es crear un controlador de eventos para el ItemDataBound
evento. Este controlador de eventos inspeccionaría los datos que se habían enlazado a DataListItem
o RepeaterItem
y afectaría al formato del control según sea necesario.
Para el control DataList, los cambios de formato para todo el elemento se pueden implementar mediante las propiedades relacionadas con el DataListItem
estilo, que incluyen el estándar Font
, ForeColor
, BackColor
, CssClass
, etc. Para afectar al formato de determinados controles web dentro de la plantilla DataList, es necesario acceder mediante programación y modificar el estilo de esos controles web. Hemos visto cómo hacerlo en el tutorial Formato personalizado basado en datos . Al igual que el control Repeater, la RepeaterItem
clase no tiene propiedades relacionadas con el estilo; por lo tanto, todos los cambios relacionados con el estilo realizados en un RepeaterItem
en el ItemDataBound
controlador de eventos deben realizarse mediante programación para acceder a los controles web y actualizarlos dentro de la plantilla.
Dado que la ItemDataBound
técnica de formato de DataList y Repeater son prácticamente idénticas, nuestro ejemplo se centrará en el uso de DataList.
Paso 1: mostrar información del producto en la lista de datos
Antes de preocuparnos por el formato, vamos a crear primero una página que use dataList para mostrar la información del producto. En el tutorial anterior creamos una lista de datos cuyo ItemTemplate
nombre, categoría, proveedor, cantidad por unidad y precio mostraron cada producto. Vamos a repetir esta funcionalidad aquí en este tutorial. Para ello, puede volver a crear dataList y su ObjectDataSource desde cero, o bien copiar esos controles desde la página creada en el tutorial anterior () y pegarlos en la página de este tutorial (Basics.aspx
Formatting.aspx
).
Una vez que haya replicado la funcionalidad de DataList y ObjectDataSource desde Basics.aspx
en Formatting.aspx
, dedique un momento a cambiar la propiedad del DataList en ID
de DataList1
a una propiedad más descriptiva en ItemDataBoundFormattingExample
. A continuación, vea DataList en un explorador. Como se muestra en la figura 1, la única diferencia de formato entre cada producto es que el color de fondo alterna.
Figura 1: Los productos aparecen en el control DataList (haga clic para ver la imagen de tamaño completo)
Para este tutorial, vamos a dar formato a DataList de modo que cualquier producto con un precio inferior a 20,00 USD tendrá su nombre y precio unitario resaltado amarillo.
Paso 2: Determinar mediante programación el valor de los datos en el controlador de eventos ItemDataBound
Puesto que solo esos productos con un precio inferior a 20,00 USD tendrán aplicado el formato personalizado, debemos poder determinar cada precio de cada producto. Al enlazar datos a dataList, DataList enumera los registros de su origen de datos y, para cada registro, crea una DataListItem
instancia, enlaza el registro del origen de datos a DataListItem
. Después de que los datos del registro particular se hayan enlazado al objeto actual DataListItem
, se desencadena el evento del DataList ItemDataBound
. Podemos crear un controlador de eventos para este evento para inspeccionar los valores de datos del actual DataListItem
y, en función de esos valores, realizar los cambios de formato necesarios.
Cree un ItemDataBound
evento para DataList y agregue el código siguiente:
Protected Sub ItemDataBoundFormattingExample_ItemDataBound _
(sender As Object, e As DataListItemEventArgs) _
Handles ItemDataBoundFormattingExample.ItemDataBound
If e.Item.ItemType = ListItemType.Item OrElse _
e.Item.ItemType = ListItemType.AlternatingItem Then
' Programmatically reference the ProductsRow instance
' bound to this DataListItem
Dim product As Northwind.ProductsRow = _
CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
Northwind.ProductsRow)
' See if the UnitPrice is not NULL and less than $20.00
If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
' TODO: Highlight the product's name and price
End If
End If
End Sub
Aunque el concepto y la semántica detrás del controlador de eventos dataList ItemDataBound
son los mismos que los usados por el controlador de eventos de RowDataBound
GridView en el tutorial Formato personalizado basado en datos , la sintaxis difiere ligeramente. Cuando se desencadena el ItemDataBound
evento, el DataListItem
enlazado a los datos se pasa al controlador de eventos correspondiente a través de e.Item
(en lugar de e.Row
, como con el controlador de eventos del GridView RowDataBound
). El controlador de eventos dataList se ItemDataBound
activa para cada fila agregada a DataList, incluidas las filas de encabezado, las filas de pie de página y las filas separadoras. Sin embargo, la información del producto solo está enlazada a las filas de datos. Por lo tanto, al usar el ItemDataBound
evento para inspeccionar los datos enlazados a DataList, primero debemos asegurarnos de que estamos trabajando con un elemento de datos. Esto se puede lograr comprobando la DataListItem
propiedad sItemType
, que puede tener uno de los ocho valores siguientes:
AlternatingItem
EditItem
Footer
Header
Item
Pager
SelectedItem
Separator
Ambos, Item
y AlternatingItem``DataListItem
, constituyen los elementos de datos de DataList. Suponiendo que estamos trabajando con un Item
o un AlternatingItem
, accedemos a la instancia real ProductsRow
enlazada al DataListItem
actual. La DataListItem
propiedad s DataItem
contiene una referencia al DataRowView
objeto , cuya Row
propiedad proporciona una referencia al objeto realProductsRow
.
A continuación, comprobamos la propiedad ProductsRow
de la instancia UnitPrice
. Dado que el campo UnitPrice
de la tabla Products admite valores NULL
, antes de intentar acceder a la propiedad UnitPrice
, primero debemos comprobar si tiene un valor NULL
usando el método IsUnitPriceNull()
. Si el valor UnitPrice
no es NULL
, comprobamos si es menos de 20,00 USD. Si realmente es inferior a 20,00 USD, entonces es necesario aplicar el formato personalizado.
Paso 3: Resaltar el nombre y el precio del producto
Una vez que sabemos que el precio de un producto es inferior a $20.00, todo lo que queda es resaltar su nombre y precio. Para ello, primero debemos referenciar programáticamente los controles Label en los cuales ItemTemplate
se muestran el nombre y el precio del producto. A continuación, necesitamos que muestren un fondo amarillo. Esta información de formato se puede aplicar modificando directamente las propiedades Etiquetas BackColor
(LabelID.BackColor = Color.Yellow
); lo ideal es que todos los asuntos relacionados con la presentación se expresen a través de hojas de estilos en cascada. De hecho, ya tenemos una hoja de estilos que proporciona el formato deseado definido en Styles.css
- AffordablePriceEmphasis
, que se creó y se explicó en el tutorial Formato personalizado basado en datos .
Para aplicar el formato, basta con establecer las propiedades de los dos controles Web de etiqueta CssClass
en AffordablePriceEmphasis
, como se muestra en el código siguiente.
' Highlight the product name and unit price Labels
' First, get a reference to the two Label Web controls
Dim ProductNameLabel As Label = CType(e.Item.FindControl("ProductNameLabel"), Label)
Dim UnitPriceLabel As Label = CType(e.Item.FindControl("UnitPriceLabel"), Label)
' Next, set their CssClass properties
If ProductNameLabel IsNot Nothing Then
ProductNameLabel.CssClass = "AffordablePriceEmphasis"
End If
If UnitPriceLabel IsNot Nothing Then
UnitPriceLabel.CssClass = "AffordablePriceEmphasis"
End If
Una vez completado el ItemDataBound
controlador de eventos, vuelva a visitar la Formatting.aspx
página en un explorador. Como se muestra en la figura 2, esos productos con un precio inferior a 20,00 USD tienen resaltado su nombre y precio.
Figura 2: Esos productos inferiores a 20,00 USD están resaltados (haga clic para ver la imagen de tamaño completo)
Nota:
Dado que DataList se representa como HTML <table>
, sus DataListItem
instancias tienen propiedades relacionadas con el estilo que se pueden establecer para aplicar un estilo específico a todo el elemento. Por ejemplo, si queríamos resaltar todo el elemento amarillo cuando su precio era inferior a 20,00 USD, podríamos haber reemplazado el código que hacía referencia a las etiquetas y establecer sus CssClass
propiedades con la siguiente línea de código: e.Item.CssClass = "AffordablePriceEmphasis"
(vea la figura 3).
Sin embargo, los elementos que componen el control Repeater no ofrecen estas propiedades de nivel de estilo. Por lo tanto, aplicar formato personalizado al repetidor requiere la aplicación de propiedades de estilo a los controles web dentro de las plantillas del repetidor, al igual que hicimos en la figura 2.
Figura 3: Todo el elemento de producto está resaltado para productos menores de 20,00 USD (haga clic para ver la imagen de tamaño completo)
Uso de funciones de formato desde dentro de la plantilla
En el tutorial Uso de TemplateFields en el control GridView vimos cómo usar una función de formato dentro de un TemplateField de GridView para aplicar formato personalizado basado en los datos enlazados a las filas de GridView. Una función de formato es un método que se puede invocar desde una plantilla y devuelve el CÓDIGO HTML que se va a emitir en su lugar. Las funciones de formato pueden residir en la clase de código subyacente de la página ASP.NET o pueden centralizarse en archivos de clase de la App_Code
carpeta o en un proyecto de biblioteca de clases independiente. Mover la función de formato fuera de la clase de código subyacente de la página de ASP.NET es ideal si planea usar la misma función de formato en varias páginas de ASP.NET o en otras aplicaciones web de ASP.NET.
Para mostrar las funciones de formato, vamos a hacer que la información del producto incluya el texto [DESCATALOGADO] junto al nombre del producto si está descatalogado. Además, vamos a tener el precio resaltado amarillo si es menor que $20.00 (como hicimos en el ItemDataBound
ejemplo del controlador de eventos); si el precio es $20.00 o superior, dejemos que no muestre el precio real, sino el texto, Llame a para una cotización de precios. En la figura 4 se muestra una captura de pantalla de la lista de productos con estas reglas de formato aplicadas.
Figura 4: Para productos costosos, el precio se reemplaza por el texto, llame a para una cotización de precio (haga clic para ver la imagen de tamaño completo)
Paso 1: Crear las funciones de formato
En este ejemplo necesitamos dos funciones de formato: una que muestre el nombre del producto junto con el texto [DESCATALOGADO], si es necesario; y otra que muestre un precio resaltado si es inferior a 20,00 USD, o el texto "Llame para obtener una cotización de precio," de lo contrario. Vamos a crear estas funciones en la clase de código subyacente de la página ASP.NET y nombrarlas DisplayProductNameAndDiscontinuedStatus
y DisplayPrice
. Ambos métodos deben devolver el CÓDIGO HTML para representarse como una cadena y ambos deben marcarse Protected
(o Public
) para poder invocarse desde la parte de sintaxis declarativa de la página ASP.NET. El código de estos dos métodos sigue:
Protected Function DisplayProductNameAndDiscontinuedStatus _
(productName As String, discontinued As Boolean) As String
' Return just the productName if discontinued is false
If Not discontinued Then
Return productName
Else
' otherwise, return the productName appended with the text "[DISCONTINUED]"
Return String.Concat(productName, " [DISCONTINUED]")
End If
End Function
Protected Function DisplayPrice(product As Northwind.ProductsRow) As String
' If price is less than $20.00, return the price, highlighted
If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
Return String.Concat("<span class="AffordablePriceEmphasis">", _
product.UnitPrice.ToString("C"), "</span>")
Else
' Otherwise return the text, "Please call for a price quote"
Return "<span>Please call for a price quote</span>"
End If
End Function
Tenga en cuenta que el DisplayProductNameAndDiscontinuedStatus
método acepta los valores de los productName
campos de datos y discontinued
como valores escalares, mientras que el DisplayPrice
método acepta una ProductsRow
instancia (en lugar de un unitPrice
valor escalar). Cualquier enfoque funcionará; sin embargo, si la función de formato está trabajando con valores escalares que pueden contener valores de base de datos NULL
(como UnitPrice
), y ni ProductName
ni Discontinued
permiten valores NULL
, se debe tener especial cuidado en el manejo de estas entradas escalares.
En concreto, el parámetro de entrada debe ser de tipo Object
, ya que el valor entrante podría ser una DBNull
instancia en lugar del tipo de datos esperado. Además, se debe realizar una comprobación para determinar si el valor entrante es o no un valor de base de datos NULL
. Es decir, si queremos que el DisplayPrice
método acepte el precio como un valor escalar, tendríamos que usar el código siguiente:
Protected Function DisplayPrice(ByVal unitPrice As Object) As String
' If price is less than $20.00, return the price, highlighted
If Not Convert.IsDBNull(unitPrice) AndAlso CType(unitPrice, Decimal) < 20 Then
Return String.Concat("<span class="AffordablePriceEmphasis">", _
CType(unitPrice, Decimal).ToString("C"), "</span>")
Else
' Otherwise return the text, "Please call for a price quote"
Return "<span>Please call for a price quote</span>"
End If
End Function
Tenga en cuenta que el unitPrice
parámetro de entrada es de tipo Object
y que la instrucción condicional se ha modificado para determinar si unitPrice
es DBNull
o no. Además, dado que el parámetro de entrada unitPrice
se pasa como un Object
, debe convertirse a un valor decimal.
Paso 2: Llamar a la función de formato desde la clase ItemTemplate de DataList
Con las funciones de formato agregadas a la clase de código subyacente de la página ASP.NET, todo lo que queda es invocar estas funciones de formato desde dataList s ItemTemplate
. Para llamar a una función de formato desde una plantilla, coloque la llamada de función dentro de la sintaxis de enlace de datos.
<%# MethodName(inputParameter1, inputParameter2, ...) %>
En el DataList ItemTemplate
el control Web ProductNameLabel
Label muestra actualmente el nombre del producto asignando a su propiedad Text
el resultado de <%# Eval("ProductName") %>
. Para que muestre el nombre más el texto [DISCONTINUED], si es necesario, actualice la sintaxis declarativa para que, en su lugar, asigne a la Text
propiedad el valor del DisplayProductNameAndDiscontinuedStatus
método. Al hacerlo, debemos pasar el nombre del producto y los valores descontinuados mediante la Eval("columnName")
sintaxis .
Eval
devuelve un valor de tipo Object
, pero el DisplayProductNameAndDiscontinuedStatus
método espera parámetros de entrada de tipo String
y Boolean
; por lo tanto, debemos convertir los valores devueltos por el Eval
método a los tipos de parámetros de entrada esperados, de la siguiente manera:
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
(bool) Eval("Discontinued")) %>'>
</asp:Label>
</h4>
Para mostrar el precio, simplemente podemos establecer la UnitPriceLabel
propiedad Label s Text
en el valor devuelto por el DisplayPrice
método , al igual que hicimos para mostrar el nombre del producto y el texto [DISCONTINUED]. Sin embargo, en lugar de pasar el UnitPrice
como un parámetro de entrada escalar, pasamos toda la instancia ProductsRow
.
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# DisplayPrice((Northwind.ProductsRow)
((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>
Con las llamadas a las funciones de formato implementadas, tómese un momento para ver nuestro progreso en un navegador. La pantalla debe ser similar a la figura 5, con los productos descontinuados incluyendo el texto [DISCONTINUED] y aquellos productos que cuestan más de $20.00 teniendo su precio reemplazado por el texto Llame para solicitar una cotización.
Figura 5: Para productos costosos, el precio se reemplaza por el texto, llame a para una cotización de precio (haga clic para ver la imagen de tamaño completo)
Resumen
Formatear el contenido de un control DataList o Repeater en función de los datos se puede realizar mediante dos técnicas. La primera técnica consiste en crear un controlador de eventos para el ItemDataBound
evento, que se desencadena a medida que cada registro del origen de datos está enlazado a un nuevo DataListItem
o RepeaterItem
. En el ItemDataBound
controlador de eventos, los datos del elemento actual se pueden examinar y, a continuación, se puede aplicar formato al contenido de la plantilla o, para DataListItem
s, a todo el elemento.
Como alternativa, el formato personalizado se puede realizar a través de funciones de formato. Una función de formato es un método que se puede invocar desde las plantillas DataList o Repeater s que devuelve el CÓDIGO HTML que se va a emitir en su lugar. A menudo, el CÓDIGO HTML devuelto por una función de formato viene determinado por los valores que se enlazan al elemento actual. Estos valores se pueden pasar a la función de formato, ya sea como valores escalares o pasando todo el objeto enlazado al elemento (como la ProductsRow
instancia).
¡Feliz programación!
Acerca del autor
Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 en 24 horas. Se puede contactar con él en mitchell@4GuysFromRolla.com.
Agradecimientos especiales a
Esta serie de tutoriales contó con la revisión de muchos revisores que fueron de gran ayuda. Los revisores principales de este tutorial fueron Yaakov Ellis, Randy Schmidt y Liz Shulok. ¿Le interesaría revisar mis próximos artículos de MSDN? Si es así, mándame un mensaje a mitchell@4GuysFromRolla.com.