Formatação do DataList e Repeater com base nos dados (C#)
por Scott Mitchell
Neste tutorial, vamos percorrer exemplos de como formatamos a aparência dos controles DataList e Repeater, usando funções de formatação em modelos ou manipulando o evento DataBound.
Introdução
Como vimos no tutorial anterior, o DataList oferece várias propriedades relacionadas ao estilo que afetam sua aparência. Em particular, vimos como atribuir classes CSS padrão às propriedades , , AlternatingItemStyle
e SelectedItemStyle
da ItemStyle
HeaderStyle
DataList. Além dessas quatro propriedades, a DataList inclui várias outras propriedades relacionadas ao estilo, como Font
, ForeColor
, BackColor
e BorderWidth
, para citar algumas. O controle Repeater não contém nenhuma propriedade relacionada ao estilo. Essas configurações de estilo devem ser feitas diretamente dentro da marcação nos modelos do Repetidor.
Muitas vezes, porém, a forma como os dados devem ser formatados depende dos próprios dados. Por exemplo, ao listar produtos, talvez queiramos exibir as informações do produto em uma cor de fonte cinza claro se ela for descontinuada, ou talvez queiramos realçar o UnitsInStock
valor se for zero. Como vimos nos tutoriais anteriores, GridView, DetailsView e FormView oferecem duas maneiras distintas de formatar sua aparência com base em seus dados:
- O
DataBound
evento cria um manipulador de eventos para o evento apropriadoDataBound
, que é acionado depois que os dados são associados a cada item (para o GridView foi oRowDataBound
evento; para DataList e Repeater é oItemDataBound
evento). Nesse manipulador de eventos, os dados apenas associados podem ser examinados e decisões de formatação tomadas. Examinamos essa técnica no tutorial Formatação Personalizada Baseada em Dados . - Formatação de funções em modelos ao usar TemplateFields nos controles DetailsView ou GridView, ou um modelo no controle FormView, podemos adicionar uma função de formatação à classe code-behind da página ASP.NET, à Camada lógica de negócios ou a qualquer outra biblioteca de classes acessível do aplicativo Web. Essa função de formatação pode aceitar um número arbitrário de parâmetros de entrada, mas deve retornar o HTML para renderizar no modelo. As funções de formatação foram examinadas primeiro no tutorial Usando TemplateFields no Controle GridView .
Essas duas técnicas de formatação estão disponíveis com os controles DataList e Repeater. Neste tutorial, vamos percorrer exemplos usando ambas as técnicas para ambos os controles.
Usando oItemDataBound
manipulador de eventos
Quando os dados são associados a um DataList, seja de um controle de fonte de dados ou por meio da atribuição programática de dados à propriedade s do DataSource
controle e da chamada de seu DataBind()
método, o evento dataList é DataBinding
acionado, a fonte de dados enumerada e cada registro de dados é associado à DataList. Para cada registro na fonte de dados, o DataList cria um DataListItem
objeto que é associado ao registro atual. Durante esse processo, o DataList gera dois eventos:
ItemCreated
é acionado depois que oDataListItem
foi criadoItemDataBound
é acionado após o registro atual ter sido associado aoDataListItem
As etapas a seguir descrevem o processo de associação de dados para o controle DataList.
O evento DataList é
DataBinding
acionadoOs dados estão associados ao DataList
Para cada registro na fonte de dados
- Criar um
DataListItem
objeto - Disparar o
ItemCreated
evento - Associar o registro ao
DataListItem
- Disparar o
ItemDataBound
evento - Adicionar o
DataListItem
àItems
coleção
- Criar um
Ao associar dados ao controle Repeater, ele progride exatamente pela mesma sequência de etapas. A única diferença é que, em vez de DataListItem
instâncias sendo criadas, o Repetidor usa RepeaterItem
s.
Observação
O leitor astuto pode ter notado uma pequena anomalia entre a sequência de etapas que ocorre quando DataList e Repeater estão associados a dados versus quando o GridView está associado aos dados. No final do processo de associação de dados, o GridView aciona o DataBound
evento; no entanto, nem o controle DataList nem Repeater têm esse evento. Isso ocorre porque os controles DataList e Repeater foram criados novamente no período ASP.NET 1.x, antes que o padrão de manipulador de eventos pré e pós-nível se tornasse comum.
Assim como no GridView, uma opção para formatação com base nos dados é criar um manipulador de eventos para o ItemDataBound
evento. Esse manipulador de eventos inspecionaria os dados que tinham acabado de ser associados ao DataListItem
ou RepeaterItem
e afetaria a formatação do controle conforme necessário.
Para o controle DataList, as alterações de formatação para todo o item podem ser implementadas usando as DataListItem
propriedades relacionadas ao estilo s, que incluem o padrão Font
, ForeColor
, BackColor
, CssClass
e assim por diante. Para afetar a formatação de controles Web específicos no modelo datalist, precisamos acessar e modificar programaticamente o estilo desses controles da Web. Vimos como fazer isso de volta no tutorial Formatação Personalizada baseada em dados . Assim como o controle Repeater, a RepeaterItem
classe não tem propriedades relacionadas ao estilo; portanto, todas as alterações relacionadas ao estilo feitas em um RepeaterItem
no ItemDataBound
manipulador de eventos devem ser feitas acessando e atualizando programaticamente controles Web dentro do modelo.
Como a ItemDataBound
técnica de formatação para DataList e Repeater é praticamente idêntica, nosso exemplo se concentrará em usar DataList.
Etapa 1: Exibindo informações do produto na DataList
Antes de nos preocuparmos com a formatação, vamos primeiro criar uma página que usa uma DataList para exibir informações do produto. No tutorial anterior , criamos uma DataList cuja ItemTemplate
exibição de cada nome, categoria, fornecedor, quantidade por unidade e preço de cada produto. Vamos repetir essa funcionalidade aqui neste tutorial. Para fazer isso, você pode recriar o DataList e seu ObjectDataSource do zero ou copiar esses controles da página criada no tutorial anterior (Basics.aspx
) e colá-los na página deste tutorial (Formatting.aspx
).
Depois de replicar a funcionalidade DataList e ObjectDataSource de Basics.aspx
para , reserve um momento para alterar a propriedade dataList de ID
DataList1
para um mais descritivoItemDataBoundFormattingExample
Formatting.aspx
. Em seguida, exiba DataList em um navegador. Como mostra a Figura 1, a única diferença de formatação entre cada produto é que a cor da tela de fundo alterna.
Figura 1: Os produtos são listados no controle DataList (clique para exibir a imagem em tamanho real)
Para este tutorial, vamos formatar a DataList de modo que todos os produtos com um preço inferior a US$ 20,00 tenham o nome e o preço unitário realçados em amarelo.
Etapa 2: Determinar programaticamente o valor dos dados no manipulador de eventos ItemDataBound
Como somente os produtos com um preço abaixo de US$ 20,00 terão a formatação personalizada aplicada, devemos ser capazes de determinar o preço de cada produto. Ao associar dados a um DataList, o DataList enumera os registros em sua fonte de dados e, para cada registro, cria uma DataListItem
instância, associando o registro da fonte de dados ao DataListItem
. Depois que os dados do registro específico tiverem sido associados ao objeto atual DataListItem
, o evento DataList será ItemDataBound
acionado. Podemos criar um manipulador de eventos para esse evento para inspecionar os valores de dados do atual DataListItem
e, com base nesses valores, fazer as alterações de formatação necessárias.
Crie um ItemDataBound
evento para DataList e adicione o seguinte código:
protected void ItemDataBoundFormattingExample_ItemDataBound
(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Programmatically reference the ProductsRow instance bound
// to this DataListItem
Northwind.ProductsRow product =
(Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
// See if the UnitPrice is not NULL and less than $20.00
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
{
// TODO: Highlight the product's name and price
}
}
}
Embora o conceito e a semântica por trás do manipulador de eventos DataList ItemDataBound
sejam os mesmos usados pelo manipulador de eventos gridView RowDataBound
no tutorial Formatação personalizada baseada em dados , a sintaxe difere ligeiramente. Quando o ItemDataBound
evento é acionado, o DataListItem
apenas associado aos dados é passado para o manipulador de eventos correspondente por meio e.Item
de (em vez de e.Row
, como com o manipulador de eventos gridView RowDataBound
). O manipulador de eventos DataList é ItemDataBound
acionado para cada linha adicionada ao DataList, incluindo linhas de cabeçalho, linhas de rodapé e linhas separadora. No entanto, as informações do produto são associadas apenas às linhas de dados. Portanto, ao usar o ItemDataBound
evento para inspecionar os dados associados à DataList, precisamos primeiro garantir que estamos trabalhando com um item de dados. Isso pode ser feito verificando a DataListItem
propriedade sItemType
, que pode ter um dos oito valores a seguir:
AlternatingItem
EditItem
Footer
Header
Item
Pager
SelectedItem
Separator
Os Item
itens de dados de DataList e AlternatingItem``DataListItem
de composição. Supondo que estamos trabalhando com um Item
ou , acessamos a instância real ProductsRow
que estava associada ao atualDataListItem
AlternatingItem
. A DataListItem
propriedade s DataItem
contém uma referência ao DataRowView
objeto , cuja Row
propriedade fornece uma referência ao objeto realProductsRow
.
Em seguida, marcar a ProductsRow
propriedade da UnitPrice
instância. Como o campo da UnitPrice
tabela Products permite NULL
valores, antes de tentar acessar a UnitPrice
propriedade, devemos primeiro marcar para ver se ela tem um NULL
valor usando o IsUnitPriceNull()
método . Se o UnitPrice
valor não NULL
for , marcar para ver se ele é menor que US$ 20,00. Se, de fato, estiver abaixo de US$ 20,00, precisaremos aplicar a formatação personalizada.
Etapa 3: Realçando o nome e o preço do produto
Quando soubermos que o preço de um produto é menor que US$ 20,00, tudo o que resta é destacar seu nome e preço. Para fazer isso, primeiro devemos referenciar programaticamente os controles Label no que exibem ItemTemplate
o nome e o preço do produto. Em seguida, precisamos que eles exibam um plano de fundo amarelo. Essas informações de formatação podem ser aplicadas modificando diretamente as propriedades labels BackColor
(LabelID.BackColor = Color.Yellow
); idealmente, porém, todas as questões relacionadas à exibição devem ser expressas por meio de folhas de estilos em cascata. Na verdade, já temos uma folha de estilos que fornece a formatação desejada definida em Styles.css
- AffordablePriceEmphasis
, que foi criada e discutida no tutorial Formatação Personalizada Baseada em Dados .
Para aplicar a formatação, basta definir as duas propriedades AffordablePriceEmphasis
de controles CssClass
Da Web de Rótulo como , conforme mostrado no seguinte código:
// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
UnitPriceLabel.CssClass = "AffordablePriceEmphasis";
Com o ItemDataBound
manipulador de eventos concluído, reveja a Formatting.aspx
página em um navegador. Como ilustra a Figura 2, esses produtos com um preço inferior a US$ 20,00 têm seu nome e preço realçados.
Figura 2: Esses produtos com menos de US$ 20,00 estão Realçados (clique para exibir a imagem em tamanho real)
Observação
Como DataList é renderizado como um HTML <table>
, suas DataListItem
instâncias têm propriedades relacionadas ao estilo que podem ser definidas para aplicar um estilo específico ao item inteiro. Por exemplo, se quiséssemos realçar o item inteiro amarelo quando seu preço fosse inferior a US$ 20,00, poderíamos ter substituído o código que referenciava os Rótulos e definido suas CssClass
propriedades com a seguinte linha de código: e.Item.CssClass = "AffordablePriceEmphasis"
(consulte a Figura 3).
Os RepeaterItem
s que compõem o controle Repeater, no entanto, não oferecem essas propriedades de nível de estilo. Portanto, a aplicação da formatação personalizada ao Repetidor requer a aplicação de propriedades de estilo aos controles da Web nos modelos do Repetidor, assim como fizemos na Figura 2.
Figura 3: o item inteiro do produto está realçado para produtos abaixo de US$ 20,00 (clique para exibir a imagem em tamanho real)
Usando funções de formatação de dentro do modelo
No tutorial Usando TemplateFields no Controle GridView , vimos como usar uma função de formatação em um TemplateField GridView para aplicar formatação personalizada com base nos dados associados às linhas do GridView. Uma função de formatação é um método que pode ser invocado de um modelo e retorna o HTML a ser emitido em seu lugar. As funções de formatação podem residir na classe code-behind da página ASP.NET ou podem ser centralizadas em arquivos de classe na App_Code
pasta ou em um projeto separado da Biblioteca de Classes. Mover a função de formatação para fora da classe code-behind da página ASP.NET é ideal se você planeja usar a mesma função de formatação em várias páginas ASP.NET ou em outros aplicativos Web ASP.NET.
Para demonstrar as funções de formatação, vamos fazer com que as informações do produto incluam o texto [DESCONTINUADO] ao lado do nome do produto se ele for descontinuado. Além disso, vamos ter o preço realçado amarelo se for menor que US$ 20,00 (como fizemos no ItemDataBound
exemplo do manipulador de eventos); se o preço for US$ 20,00 ou superior, não vamos exibir o preço real, mas sim o texto, chame uma cotação de preço. A Figura 4 mostra uma captura de tela da listagem de produtos com essas regras de formatação aplicadas.
Figura 4: Para Produtos Caros, o Preço é Substituído pelo Texto, chame por uma cotação de preço (clique para exibir a imagem em tamanho real)
Etapa 1: Criar as funções de formatação
Para este exemplo, precisamos de duas funções de formatação, uma que exibe o nome do produto junto com o texto [DESCONTINUADO], se necessário, e outra que exibe um preço realçado se for menor que US$ 20,00 ou o texto, chame uma cotação de preço caso contrário. Vamos criar essas funções na classe code-behind da página ASP.NET e nomeá-las DisplayProductNameAndDiscontinuedStatus
e DisplayPrice
. Ambos os métodos precisam retornar o HTML para renderizar como uma cadeia de caracteres e ambos precisam ser marcados Protected
(ou Public
) para serem invocados da parte de sintaxe declarativa da página ASP.NET. O código para esses dois métodos segue:
protected string DisplayProductNameAndDiscontinuedStatus
(string productName, bool discontinued)
{
// Return just the productName if discontinued is false
if (!discontinued)
return productName;
else
// otherwise, return the productName appended with the text "[DISCONTINUED]"
return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
// If price is less than $20.00, return the price, highlighted
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
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>";
}
Observe que o DisplayProductNameAndDiscontinuedStatus
método aceita os valores dos campos de productName
dados e discontinued
como valores escalares, enquanto o DisplayPrice
método aceita uma ProductsRow
instância (em vez de um unitPrice
valor escalar). Qualquer abordagem funcionará; no entanto, se a função de formatação estiver trabalhando com valores escalares que podem conter valores de banco de dados NULL
(como UnitPrice
; nem ProductName
nem Discontinued
permitir NULL
valores), deve-se tomar cuidado especial no tratamento dessas entradas escalares.
Em particular, o parâmetro de entrada deve ser do tipo Object
, pois o valor de entrada pode ser uma DBNull
instância em vez do tipo de dados esperado. Além disso, um marcar deve ser feito para determinar se o valor de entrada é ou não um valor de banco de dadosNULL
. Ou seja, se quiséssemos que o DisplayPrice
método aceitasse o preço como um valor escalar, teríamos que usar o seguinte código:
protected string DisplayPrice(object unitPrice)
{
// If price is less than $20.00, return the price, highlighted
if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
return string.Concat("<span class=\"AffordablePriceEmphasis\">",
((decimal) unitPrice).ToString("C"), "</span>");
else
// Otherwise return the text, "Please call for a price quote"
return "<span>Please call for a price quote</span>";
}
Observe que o unitPrice
parâmetro de entrada é do tipo Object
e que a instrução condicional foi modificada para verificar se unitPrice
é DBNull
ou não. Além disso, como o unitPrice
parâmetro de entrada é passado como um Object
, ele deve ser convertido em um valor decimal.
Etapa 2: Chamando a função de formatação do ItemTemplate de DataList
Com as funções de formatação adicionadas à nossa classe code-behind da página ASP.NET, tudo o que resta é invocar essas funções de formatação do DataList s ItemTemplate
. Para chamar uma função de formatação de um modelo, coloque a chamada de função dentro da sintaxe de associação de dados:
<%# MethodName(inputParameter1, inputParameter2, ...) %>
No DataList s ItemTemplate
, o ProductNameLabel
controle Web Label atualmente exibe o nome do produto atribuindo a sua Text
propriedade o resultado de <%# Eval("ProductName") %>
. Para que ele exiba o nome mais o texto [DESCONTINUADO], se necessário, atualize a sintaxe declarativa para que, em vez disso, atribua à propriedade o Text
valor do DisplayProductNameAndDiscontinuedStatus
método. Ao fazer isso, devemos passar o nome do produto e os valores descontinuados usando a Eval("columnName")
sintaxe . Eval
retorna um valor do tipo Object
, mas o DisplayProductNameAndDiscontinuedStatus
método espera parâmetros de entrada do tipo String
e Boolean
; portanto, devemos converter os valores retornados pelo Eval
método para os tipos de parâmetro de entrada esperados, da seguinte forma:
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
(bool) Eval("Discontinued")) %>'>
</asp:Label>
</h4>
Para exibir o preço, podemos simplesmente definir a UnitPriceLabel
propriedade Label s Text
para o valor retornado pelo DisplayPrice
método , assim como fizemos para exibir o nome do produto e o texto [DESCONTINUADO]. No entanto, em vez de passar o UnitPrice
como um parâmetro de entrada escalar, passamos a instância inteira ProductsRow
:
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# DisplayPrice((Northwind.ProductsRow)
((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>
Com as chamadas para as funções de formatação em vigor, reserve um momento para exibir nosso progresso em um navegador. Sua tela deve ser semelhante à Figura 5, com os produtos descontinuados incluindo o texto [DESCONTINUADO] e esses produtos custando mais de US$ 20,00, tendo seu preço substituído pelo texto Chame para uma cotação de preço .
Figura 5: Para Produtos Caros, o Preço é Substituído pelo Texto, chame por uma cotação de preço (Clique para exibir a imagem em tamanho real)
Resumo
A formatação do conteúdo de um controle DataList ou Repeater com base nos dados pode ser realizada usando duas técnicas. A primeira técnica é criar um manipulador de eventos para o ItemDataBound
evento, que é acionado à medida que cada registro na fonte de dados está associado a um novo DataListItem
ou RepeaterItem
. ItemDataBound
No manipulador de eventos, os dados do item atual podem ser examinados e, em seguida, a formatação pode ser aplicada ao conteúdo do modelo ou, para DataListItem
s, ao próprio item inteiro.
Como alternativa, a formatação personalizada pode ser realizada por meio de funções de formatação. Uma função de formatação é um método que pode ser invocado dos modelos DataList ou Repeater s que retorna o HTML para emitir em seu lugar. Geralmente, o HTML retornado por uma função de formatação é determinado pelos valores associados ao item atual. Esses valores podem ser passados para a função de formatação, seja como valores escalares ou passando todo o objeto que está sendo associado ao item (como a ProductsRow
instância).
Programação feliz!
Sobre o autor
Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos Especiais
Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Yaakov Ellis, Randy Schmidt e Liz Shulok. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.