Formatação do DataList e Repeater com base nos dados (C#)

por Scott Mitchell

Baixar PDF

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 , , AlternatingItemStylee SelectedItemStyle da ItemStyleHeaderStyleDataList. Além dessas quatro propriedades, a DataList inclui várias outras propriedades relacionadas ao estilo, como Font, ForeColor, BackColore 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 apropriado DataBound , que é acionado depois que os dados são associados a cada item (para o GridView foi o RowDataBound evento; para DataList e Repeater é o ItemDataBound 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 oItemDataBoundmanipulador 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 o DataListItem foi criado
  • ItemDataBound é acionado após o registro atual ter sido associado ao DataListItem

As etapas a seguir descrevem o processo de associação de dados para o controle DataList.

  1. O evento DataList é DataBinding acionado

  2. Os dados estão associados ao DataList

    Para cada registro na fonte de dados

    1. Criar um DataListItem objeto
    2. Disparar o ItemCreated evento
    3. Associar o registro ao DataListItem
    4. Disparar o ItemDataBound evento
    5. Adicionar o DataListItem à Items coleção

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 RepeaterItems.

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, CssClasse 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 IDDataList1 para um mais descritivoItemDataBoundFormattingExampleFormatting.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.

Os produtos são listados no controle DataList

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 atualDataListItemAlternatingItem. 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 NULLfor , 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 AffordablePriceEmphasisde 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.

Esses produtos com menos de US$ 20,00 estã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.

O item de produto inteiro está realçado para produtos abaixo de US$ 20,00

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.

Captura de tela mostrando produtos listados no controle DataList, com o preço dos produtos custando mais de US$ 20,00 substituído pelo texto:

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 .

Captura de tela mostrando os produtos listados no controle DataList, com o preço dos produtos custando mais de US$ 20,00 substituídos pelo texto

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.