Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
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 programaticamente dados agregados. 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 sob encomenda 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 programaticamente dados agregados.
Esta tarefa coloca-nos 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?
- Injetar 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 sob encomenda para produtos nessa categoria.
Figura 1: Informações de resumo são exibidas na linha de rodapé do GridView (Clique para visualizar a imagem em tamanho real)
Este tutorial, que apresenta uma interface mestre/detalhe de categoria para produtos, baseia-se nos conceitos abordados no tutorial anterior, Master/Detail Filtering With a DropDownList. Caso ainda não tenha seguido o tutorial anterior, por favor, faça isso antes de continuar com este.
Etapa 1: Adicionando o DropDownList de categorias e o GridView de produtos
Antes de nos preocuparmos em adicionar informações resumidas ao rodapé do GridView, vamos primeiro simplesmente construir o relatório mestre/detalhe. Depois de concluir esta primeira etapa, veremos como incluir dados resumidos.
Comece por abrir a página SummaryDataInFooter.aspx na pasta CustomFormatting. Adicione um controle DropDownList e defina-o ID como Categories. Em seguida, clique no link "Escolher Fonte de Dados" da etiqueta inteligente do DropDownList e opte por adicionar um novo ObjectDataSource nomeado CategoriesDataSource que invoque o método CategoriesBLL da classe GetCategories().
Figura 2: Adicionar um novo ObjectDataSource nomeado CategoriesDataSource (Clique para visualizar a imagem em tamanho real)
Figura 3: Fazer com que o ObjectDataSource invoque o método da CategoriesBLL classe (GetCategories() imagem em tamanho real)
Depois de configurar o ObjectDataSource, o assistente leva-nos de volta ao assistente de configuração da 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 ListItem do DropDownList. Tenha o CategoryName campo exibido e use o CategoryID como o valor.
Figura 4: Use os CategoryName e CategoryID campos como o Text e Value para os ListItem, respectivamente (Clique para visualizar a imagem completa)
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 disso, porém, selecione a caixa de seleção Ativar AutoPostBack na etiqueta inteligente do DropDownList. Conforme discutido no tutorial Filtragem Mestre/Detalhe com uma DropDownList, ao definir a propriedade da DropDownList para AutoPostBack, a página será recarregada sempre que o valor do 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 "Enable AutoPostBack" no Tag Inteligente do DropDownList (Clique para visualizar a imagem em tamanho real)
Adicione um controle GridView à página para exibir os produtos para a categoria selecionada. Defina o GridView como IDProductsInCategory e associe-o a um novo ObjectDataSource chamado ProductsInCategoryDataSource.
Figura 6: Adicionar um novo ObjectDataSource nomeado ProductsInCategoryDataSource (Clique para visualizar a imagem em tamanho normal)
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 (GetProductsByCategoryID(categoryID) imagem em tamanho real)
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, tenha o parâmetro extraído da Categories DropDownList.
Figura 8: Obter o valor do parâmetro a partir da lista suspensa de Categorias Selecionadas (categoryID)
Depois de concluir o assistente, o "GridView" terá um BoundField para cada uma das propriedades do produto. Vamos limpar esses BoundFields para que apenas o ProductName, UnitPrice, UnitsInStocke UnitsOnOrder BoundFields sejam exibidos. Sinta-se à vontade para adicionar quaisquer configurações de nível de campo aos BoundFields restantes (como formatar o UnitPrice como uma 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, preço unitário, unidades em estoque e unidades sob encomenda para os produtos que pertencem à categoria selecionada.
Figura 9: Obter o valor do parâmetro da lista suspensa das categorias selecionadas (categoryID)
Etapa 2: Mostrar 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 propriedades ShowHeader e ShowFooter, respectivamente, com ShowHeader como padrão para true e ShowFooter como padrão 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 visualizar a imagem em tamanho real)
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 o 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 visualizar a imagem em tamanho real)
A linha de rodapé na Figura 11 não se destaca, pois tem um fundo branco. Vamos criar uma classe CSS em FooterStyle que especifique um plano de fundo vermelho escuro e, em seguida, configurar o arquivo Skin no Tema Styles.css para atribuir essa classe CSS à propriedade GridView.skin do DataWebControls GridView. Se você precisar aprimorar Skins e Themes, consulte novamente 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 classe FooterStyle CSS é semelhante em estilo à classe HeaderStyle, embora a cor de fundo da HeaderStyle seja sutilmente mais escura e seu texto seja exibido em negrito. Além disso, o texto no rodapé está alinhado à direita, enquanto o texto do cabeçalho está centralizado.
Em seguida, para associar essa classe CSS a todos os rodapés do GridView, abra o arquivo GridView.skin no Tema DataWebControls e defina a propriedade FooterStyle do CssClass. Após essa adição, a marcação do arquivo deve ter a seguinte aparência:
<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 visualizar a imagem em tamanho real)
Etapa 3: Computando os dados de resumo
Com o rodapé do GridView exibido, o próximo desafio que enfrentamos é como calcular os dados de resumo. Há duas maneiras de calcular essas informações agregadas:
Através de uma consulta SQL, poderíamos emitir uma consulta adicional ao banco de dados para calcular os dados de resumo para uma determinada categoria. SQL inclui uma série de funções agregadas juntamente com uma
GROUP BYclá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.aspxpágina, mas sim criando um método noProductsTableAdaptere noProductsBLL.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
RowDataBoundGridView é acionado uma vez para cada linha que está sendo adicionada ao GridView após sua vinculação de dados. Ao criar um manipulador de eventos para esse evento, podemos manter um total em execução dos valores que queremos agregar. Após a última linha de dados ter sido vinculada ao GridView, temos os totais e as informações necessárias para calcular a média.
Normalmente, utilizo a segunda abordagem, pois ela salva 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 de execução usando o RowDataBound manipulador de eventos.
Crie um RowDataBound manipulador de 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 seguintes quatro variáveis de nível de página:
-
_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 foi apenas 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 ). Somos responsáveis pelo acompanhamento tanto do total corrente UnitPrice quanto do número de registos não-NULLUnitPrice, 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 vinculada 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 totais em execução terão sido concluídos. O último passo, 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 ToString("c") faz 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 visualizar 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 ShowFooter do GridView é definida como true e pode ter o texto em suas células definido programaticamente por meio do manipulador de eventos RowDataBound. A computação dos dados de resumo pode ser feita consultando novamente o banco de dados ou usando código na classe code-behind da página ASP.NET para calcular programaticamente os dados de resumo.
Este tutorial conclui nosso exame de formatação personalizada com os controles GridView, DetailsView e FormView. Nosso próximo tutorial inicia nossa exploração de inserir, atualizar e excluir dados usando esses mesmos controles.
Feliz Programação!
Sobre o Autor
Scott Mitchell, autor de sete livros sobre ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias Web da Microsoft desde 1998. Scott trabalha como consultor, formador e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Ele pode ser contatado em mitchell@4GuysFromRolla.com.