Exibir informações de resumo no rodapé do GridView (C#)
por Scott Mitchell
As informações de resumo geralmente são exibidas na parte inferior do relatório em uma linha de resumo. O controle GridView pode incluir uma linha de rodapé em cujas células podemos injetar dados agregados programaticamente. Neste tutorial, veremos como exibir dados agregados nesta linha de rodapé.
Introdução
Além de ver os preços de cada um dos produtos, unidades em estoque, unidades em ordem e níveis de reordenação, um usuário também pode estar interessado em informações agregadas, como o preço médio, o número total de unidades em estoque e assim por diante. Essas informações resumidas geralmente são exibidas na parte inferior do relatório em uma linha de resumo. O controle GridView pode incluir uma linha de rodapé em cujas células podemos injetar dados agregados programaticamente.
Esta tarefa nos apresenta três desafios:
- Configurando o GridView para exibir sua linha de rodapé
- Determinação dos dados resumidos; ou seja, como calculamos o preço médio ou o total das unidades em estoque?
- Injetando os dados de resumo nas células apropriadas da linha de rodapé
Neste tutorial, veremos como superar esses desafios. Especificamente, criaremos uma página que lista as categorias em uma lista suspensa com os produtos da categoria selecionada exibidos em um GridView. O GridView incluirá uma linha de rodapé que mostra o preço médio e o número total de unidades em estoque e no pedido de produtos nessa categoria.
Figura 1: As informações resumidas são exibidas na linha de rodapé do GridView (clique para exibir a imagem em tamanho real)
Este tutorial, com sua categoria para a interface de mestre/detalhes de produtos, baseia-se nos conceitos abordados no tutorial anterior Filtragem de Mestre/Detalhes com uma Lista Suspensa . Se você ainda não trabalhou no tutorial anterior, faça-o antes de continuar com este.
Etapa 1: Adicionando as categorias DropDownList e Products GridView
Antes de nos preocuparmos com a adição de informações resumidas ao rodapé do GridView, vamos primeiro simplesmente criar o relatório mestre/detalhado. Depois de concluir essa primeira etapa, veremos como incluir dados resumidos.
Comece abrindo a SummaryDataInFooter.aspx
CustomFormatting
página na pasta. Adicione um controle DropDownList e defina-o ID
como Categories
. Em seguida, clique no link Escolher Fonte de Dados na marca inteligente do DropDownList e opte por adicionar um novo ObjectDataSource chamado CategoriesDataSource
que invoca o CategoriesBLL
método da GetCategories()
classe.
Figura 2: Adicionar um novo ObjectDataSource nomeado CategoriesDataSource
(clique para exibir a imagem em tamanho real)
Figura 3: Fazer com que o ObjectDataSource invoque o método da GetCategories()
classe (clique para exibir a CategoriesBLL
imagem em tamanho completo)
Depois de configurar o ObjectDataSource, o assistente nos retorna ao assistente de Configuração de Fonte de Dados do DropDownList, a partir do qual precisamos especificar qual valor de campo de dados deve ser exibido e qual deve corresponder ao valor do s do ListItem
DropDownList. Exiba o CategoryName
campo e use o CategoryID
como valor.
Figura 4: Use os CategoryName
campos e CategoryID
como o Text
e Value
para o s, respectivamente (clique para exibir a ListItem
imagem em tamanho real)
Neste ponto, temos um DropDownList (Categories
) que lista as categorias no sistema. Agora precisamos adicionar um GridView que lista os produtos que pertencem à categoria selecionada. Antes de fazermos isso, porém, reserve um momento para marcar a caixa de seleção Habilitar AutoPostBack na marca inteligente do DropDownList. Conforme discutido no tutorial Filtragem mestre/detalhada com um DropDownList , definindo a propriedade do DropDownList AutoPostBack
como true
a página será postada de volta sempre que o valor DropDownList for alterado. Isso fará com que o GridView seja atualizado, mostrando esses produtos para a categoria recém-selecionada. Se a AutoPostBack
propriedade estiver definida como false
(o padrão), alterar a categoria não causará um postback e, portanto, não atualizará os produtos listados.
Figura 5: Marque a caixa de seleção Habilitar AutoPostBack na marca inteligente do DropDownList (clique para exibir a imagem em tamanho real)
Adicione um controle GridView à página para exibir os produtos da categoria selecionada. Defina o GridView ID
como ProductsInCategory
e associe-o a um novo ObjectDataSource chamado ProductsInCategoryDataSource
.
Figura 6: Adicionar um novo ObjectDataSource nomeado ProductsInCategoryDataSource
(clique para exibir a imagem em tamanho real)
Configure o ObjectDataSource para que ele invoque o ProductsBLL
método da GetProductsByCategoryID(categoryID)
classe.
Figura 7: Fazer com que o ObjectDataSource invoque o método (clique para exibir a GetProductsByCategoryID(categoryID)
imagem em tamanho completo)
Como o GetProductsByCategoryID(categoryID)
método recebe um parâmetro de entrada, na etapa final do assistente, podemos especificar a origem do valor do parâmetro. Para exibir esses produtos da categoria selecionada, faça com que o parâmetro seja extraído do Categories
DropDownList.
Figura 8: Obter o categoryID
valor do parâmetro da lista suspensa de categorias selecionadas (clique para exibir a imagem em tamanho completo)
Depois de concluir o assistente, o GridView terá um BoundField para cada uma das propriedades do produto. Vamos limpar esses BoundFields para que apenas os ProductName
UnitPrice
, , UnitsInStock
e UnitsOnOrder
BoundFields sejam exibidos. Sinta-se à vontade para adicionar qualquer configuração de nível de campo aos BoundFields restantes (como formatar o UnitPrice
como moeda). Depois de fazer essas alterações, a marcação declarativa do GridView deve ser semelhante à seguinte:
<asp:GridView ID="ProductsInCategory" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsInCategoryDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="UnitsInStock"
HeaderText="Units In Stock" SortExpression="UnitsInStock">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="Units On Order" SortExpression="UnitsOnOrder">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
</Columns>
</asp:GridView>
Neste ponto, temos um relatório mestre/detalhado totalmente funcional que mostra o nome, o preço unitário, as unidades em estoque e as unidades em ordem para os produtos que pertencem à categoria selecionada.
Figura 9: Obter o valor do categoryID
parâmetro da lista suspensa de categorias selecionadas (clique para exibir a imagem em tamanho real)
Etapa 2: Exibindo um rodapé no GridView
O controle GridView pode exibir uma linha de cabeçalho e rodapé. Essas linhas são exibidas dependendo dos valores das ShowHeader
propriedades e ShowFooter
, respectivamente, com ShowHeader
o padrão para true
e ShowFooter
para false
. Para incluir um rodapé no GridView, basta definir sua ShowFooter
propriedade como true
.
Figura 10: Definir a propriedade do ShowFooter
GridView como true
(clique para exibir a imagem em tamanho completo)
A linha de rodapé tem uma célula para cada um dos campos definidos no GridView; No entanto, essas células estão vazias por padrão. Reserve um momento para ver nosso progresso em um navegador. Com a ShowFooter
propriedade agora definida como true
, o GridView inclui uma linha de rodapé vazia.
Figura 11: O GridView agora inclui uma linha de rodapé (clique para exibir a imagem em tamanho real)
A linha de rodapé na Figura 11 não se destaca, pois tem um fundo branco. Vamos criar uma FooterStyle
classe CSS que Styles.css
especifica um plano de fundo vermelho escuro e, em seguida, configurar o GridView.skin
arquivo Skin no DataWebControls
Theme para atribuir essa classe CSS à propriedade do CssClass
GridViewFooterStyle
. Se você precisar revisar Skins e Themes, consulte o tutorial Exibindo dados com o ObjectDataSource .
Comece adicionando a seguinte classe CSS a Styles.css
:
.FooterStyle
{
background-color: #a33;
color: White;
text-align: right;
}
A FooterStyle
classe CSS é semelhante em estilo à HeaderStyle
classe, embora a HeaderStyle
cor de fundo do seja sutilmente mais escura e seu texto seja exibido em negrito. Além disso, o texto no rodapé é alinhado à direita, enquanto o texto do cabeçalho é centralizado.
Em seguida, para associar essa classe CSS a cada rodapé do GridView, abra o GridView.skin
arquivo no DataWebControls
Tema e defina a FooterStyle
propriedade do CssClass
. Após essa adição, a marcação do arquivo deve ficar assim:
<asp:GridView runat="server" CssClass="DataWebControlStyle">
<AlternatingRowStyle CssClass="AlternatingRowStyle" />
<RowStyle CssClass="RowStyle" />
<HeaderStyle CssClass="HeaderStyle" />
<FooterStyle CssClass="FooterStyle" />
<SelectedRowStyle CssClass="SelectedRowStyle" />
</asp:GridView>
Como mostra a captura de tela abaixo, essa alteração faz com que o rodapé se destaque com mais clareza.
Figura 12: A linha de rodapé do GridView agora tem uma cor de fundo avermelhada (clique para exibir a imagem em tamanho real)
Etapa 3: Calculando os dados resumidos
Com o rodapé do GridView exibido, o próximo desafio que enfrentamos é como calcular os dados resumidos. Há duas maneiras de calcular essas informações agregadas:
Por meio de uma consulta SQL, poderíamos emitir uma consulta adicional ao banco de dados para calcular os dados resumidos de uma categoria específica. O SQL inclui várias funções agregadas junto com uma
GROUP BY
cláusula para especificar os dados sobre os quais os dados devem ser resumidos. A seguinte consulta SQL traria de volta as informações necessárias:SELECT CategoryID, AVG(UnitPrice), SUM(UnitsInStock), SUM(UnitsOnOrder) FROM Products WHERE CategoryID = categoryID GROUP BY CategoryID
É claro que você não gostaria de emitir essa consulta diretamente da
SummaryDataInFooter.aspx
página, mas sim criando um método no e noProductsTableAdapter
ProductsBLL
.Calcule essas informações à medida que elas estão sendo adicionadas ao GridView, conforme discutido no tutorial Formatação personalizada com base em dados , o manipulador de eventos do
RowDataBound
GridView é acionado uma vez para cada linha que está sendo adicionada ao GridView depois que ele foi associado a dados. Ao criar um manipulador de eventos para esse evento, podemos manter um total em execução dos valores que queremos agregar. Depois que a última linha de dados tiver sido associada ao GridView, teremos os totais e as informações necessárias para calcular a média.
Normalmente, emprego a segunda abordagem, pois ela economiza uma viagem ao banco de dados e o esforço necessário para implementar a funcionalidade de resumo na Camada de Acesso a Dados e na Camada de Lógica de Negócios, mas qualquer uma das abordagens seria suficiente. Para este tutorial, vamos usar a segunda opção e acompanhar o total acumulado usando o RowDataBound
manipulador de eventos.
Crie um manipulador de RowDataBound
eventos para o GridView selecionando o GridView no Designer, clicando no ícone de raio na janela Propriedades e clicando duas vezes no RowDataBound
evento. Isso criará um novo manipulador de eventos nomeado ProductsInCategory_RowDataBound
na SummaryDataInFooter.aspx
classe code-behind da página.
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
}
Para manter um total em execução, precisamos definir variáveis fora do escopo do manipulador de eventos. Crie as quatro variáveis de nível de página a seguir:
_totalUnitPrice
, do tipodecimal
_totalNonNullUnitPriceCount
, do tipoint
_totalUnitsInStock
, do tipoint
_totalUnitsOnOrder
, do tipoint
Em seguida, escreva o código para incrementar essas três variáveis para cada linha de dados encontrada no manipulador de RowDataBound
eventos.
// Class-scope, running total variables...
decimal _totalUnitPrice = 0m;
int _totalNonNullUnitPriceCount = 0;
int _totalUnitsInStock = 0;
int _totalUnitsOnOrder = 0;
protected void ProductsInCategory_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Reference the ProductsRow via the e.Row.DataItem property
Northwind.ProductsRow product =
(Northwind.ProductsRow)
((System.Data.DataRowView)e.Row.DataItem).Row;
// Increment the running totals (if they are not NULL!)
if (!product.IsUnitPriceNull())
{
_totalUnitPrice += product.UnitPrice;
_totalNonNullUnitPriceCount++;
}
if (!product.IsUnitsInStockNull())
_totalUnitsInStock += product.UnitsInStock;
if (!product.IsUnitsOnOrderNull())
_totalUnitsOnOrder += product.UnitsOnOrder;
}
}
O RowDataBound
manipulador de eventos começa garantindo que estamos lidando com um DataRow. Uma vez que isso tenha sido estabelecido, a Northwind.ProductsRow
instância que acabou de ser vinculada ao GridViewRow
objeto em e.Row
é armazenada na variável product
. Em seguida, as variáveis totais em execução são incrementadas pelos valores correspondentes do produto atual (supondo que elas não contenham um valor de banco de dados NULL
). Acompanhamos o total acumulado UnitPrice
e o número de não-registrosNULL
UnitPrice
porque o preço médio é o quociente desses dois números.
Etapa 4: Exibindo os dados de resumo no rodapé
Com os dados de resumo totalizados, a última etapa é exibi-los na linha de rodapé do GridView. Essa tarefa também pode ser realizada programaticamente por meio do manipulador de RowDataBound
eventos. Lembre-se de que o RowDataBound
manipulador de eventos é acionado para cada linha associada ao GridView, incluindo a linha de rodapé. Portanto, podemos aumentar nosso manipulador de eventos para exibir os dados na linha de rodapé usando o seguinte código:
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
... Increment the running totals ...
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
... Display the summary data in the footer ...
}
}
Como a linha de rodapé é adicionada ao GridView depois que todas as linhas de dados foram adicionadas, podemos ter certeza de que, quando estivermos prontos para exibir os dados de resumo no rodapé, os cálculos de total acumulado terão sido concluídos. A última etapa, então, é definir esses valores nas células do rodapé.
Para exibir texto em uma célula de rodapé específica, use e.Row.Cells[index].Text = value
, onde a Cells
indexação começa em 0. O código a seguir calcula o preço médio (o preço total dividido pelo número de produtos) e o exibe junto com o número total de unidades em estoque e unidades em ordem nas células de rodapé apropriadas do GridView.
protected void ProductsInCategory_RowDataBound
(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
... <i>Increment the running totals</i> ...
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
// Determine the average UnitPrice
decimal avgUnitPrice = _totalUnitPrice / (decimal) _totalNonNullUnitPriceCount;
// Display the summary data in the appropriate cells
e.Row.Cells[1].Text = "Avg.: " + avgUnitPrice.ToString("c");
e.Row.Cells[2].Text = "Total: " + _totalUnitsInStock.ToString();
e.Row.Cells[3].Text = "Total: " + _totalUnitsOnOrder.ToString();
}
}
A Figura 13 mostra o relatório depois que esse código foi adicionado. Observe como o faz ToString("c")
com que as informações de resumo do preço médio sejam formatadas como uma moeda.
Figura 13: A linha de rodapé do GridView agora tem uma cor de fundo avermelhada (clique para exibir a imagem em tamanho real)
Resumo
A exibição de dados de resumo é um requisito de relatório comum, e o controle GridView facilita a inclusão dessas informações em sua linha de rodapé. A linha de rodapé é exibida quando a propriedade do GridView ShowFooter
é definida como true
e pode ter o texto em suas células definido programaticamente por meio do manipulador de RowDataBound
eventos. O cálculo dos dados de resumo pode ser feito consultando novamente o banco de dados ou usando o código na classe code-behind da página de ASP.NET para calcular programaticamente os dados de resumo.
Este tutorial conclui nosso exame da formatação personalizada com os controles GridView, DetailsView e FormView. Nosso próximo tutorial inicia nossa exploração de inserção, atualização e exclusão de dados usando esses mesmos controles.
Boa programação!
Sobre o autor
Scott Mitchell, autor de sete livros ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independente. 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.