Translate this page now :



»Programação
»Programação.NET
»Banco de Dados
»Webdesign
»Office
» Certificações Microsoft 4
»Treinamentos4
»Programação 4
»Webdesign«
»Office & User Tips«
»Grupos de Usuários
»Células Acadêmicas«
intcontpiada : 118
Vá dormir
Você já está cadastrado e participa do grupo de usuários de sua cidade ? Se não, comente o porque.
 
 
Faça um pequeno teste com 10 questões de VB
.:.
Teste seus conhecimentos em Visual Basic, SQL Server e ASP 3.0 com nossas provas on-line
.:.
Aprimore seus conhecimentos em programação com nosso treinamento on-line de lógica de programação
.:.
Veja nosso calendário de treinamentos
Gostou da Página?
Então

para um amigo!
 





Por Dennes Torres
dennes@bufaloinfo.com.br
Dennes Torres possui as certificações MCAD, MCSD,MCSE, MCDBA e MCT. Atualmente atua Como diretor da Búfalo Informática, líder do grupo de usuários DevASPNet no Rio de Janeiro e membro da liderança dos grupos getWindows e devSQL, também do Rio de Janeiro, podendo sempre ser encontrado na lista de discussão do grupo DevASPNet (devaspnet-subscribe@yahoogrupos.com.br) bem como nas reuniões do grupo. Mantém dois blogs em http://cidadaocarioca.blogspot.com

Truques diversos com a DataGrid

Pesquisa personalizada
Pesquisar Dicas:







A DataGrid é um dos objetos mais versáteis do ASP.NET. Vamos fazer algumas experiências com a DataGrid e ver o quão versátil é este objeto.

Criando uma lista de produtos

Insira um dataAdapter ligado ao banco northwind com a seguinte query :

Gere um dataSet

Monte a grid com os seguintes campos :

ProductId
ProductName
UnitPrice
UnitsInStock

Faça um auto-format

Realizando um cálculo nos registros

Vamos calcular na grid o valor total em estoque do produto (preço unitário * quantidade em estoque).

Poderíamos fazer esse cálculo utilizando um campo com expressão no dataSet, conforme explicado no artigo em http://www.bufaloinfo.com.br/artigos/artigo0703.asp , mas nosso objetivo aqui é fazer testes com a dataGrid

O truque para fazer o cálculo é que a configuração de dataBings é bem flexivel. Não precisamos vincular o label a um campo específico, mas podemos sim vincula-lo a uma expressão de dataBinding. Assim sendo o vínculo do label pode ser feito com a multiplicação dos dois campos.

 

Criando uma toolTip

Os labels no ASP.NET tem uma propriedade interessante, Tooltip. No internet explorer esta propriedade gera um efeito semelhante a uma tooltip do windows form : Ao passarmos o mouse sobre o label temos uma mensagem adicional.

Para experimentarmos isso, podemos criar um tooltip no nome do produto : Ao passarmos o mouse sobre o nome do produto veremos a sua categoria.

Para podermos criar este tooltip deveremos utilizar o evento ItemDataBound. Na personalização da grid existem 2 importantes eventos, é interessante diferencia-los :

Como no nosso exemplo desejamos manipular os dados, deveremos utilizar o itemDataBound. Veja como fica :

   66     Private Sub dg_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemDataBound

   67 

   68         If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

   69 

   70             Dim lbl As Label

   71             lbl = e.Item.FindControl("lblproduto")

   72             lbl.ToolTip = e.Item.DataItem("categoryname")

   73         End If

   74     End Sub

Observe que tomamos o cuidado de verificar o tipo de linha, itemType. Afinal desejamos exibir o tooltip nas linhas de dados, não no rodapé ou no título.

Simplificando a ToolTip

A criação desta ToolTip serve de exemplo de como a exibição de dados na DataGrid é personalizável, mas temos forma mais fácil de fazer isso.

Como a Tooltip é uma propriedade do label, basta transformar a coluna produto em template, editar o template e fazer um vinculo entre o campo categoryName e a propriedade Tooltip, assim não precisamos do código para gerar a Tooltip.


Marcando linhas conforme a movimentação do mouse

Esse é um truque visual muito interessante : Fazer com que ao mover o mouse sobre a dataGrid as linhas sejam marcadas, destacando desta forma a linha na qual o mouse se encontra. Este podemos fazer utilizando o itemCreated, já que envolve apenas layout e não dados. Veja como fica :

  113     Private Sub DG_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DG.ItemCreated

  114 

  115 

  116         If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then

  117 

  118 

  119             e.Item.Attributes.Add("onMouseOver", "selecionaGrid(this)")

  120 

  121             e.Item.Attributes.Add("onMouseOut", "deSelecionaGrid(this)")

  122 

  123         End If

  124     End Sub

Neste caso dependemos de código javascript para gerar o efeito de troca de cor no lado client. Com o código acima fizemos a ligação da linha da grid (que é um TR - tag TR do HTML) a dois eventos do javascript, onMouseOver e onMouseOut. Nos dois casos chamamos functions em javascript, estas functions deverão estar no HTML.

<script language=javascript>
<!--

var cor;

function selecionaGrid( elemento )
{
cor=elemento.style.backgroundColor;
elemento.style.backgroundColor = "#a2bf82";
}

// Função para mudar a linha ao de-selecionar
function deSelecionaGrid( elemento)
{
elemento.style.backgroundColor = cor;
}

//-->
</script>

A function selecionaGrid guarda a cor atual da linha e troca a cor. Já a função deSelecionaGrid volta para a cor original.

 

Totalizando a coluna de total do estoque

Mais um recurso interessante que podemos realizar utilizando o itemDataBound. Já que este evento ocorre em cada linha da DataGrid podemos com facilidade totalizar os dados e exibi-los no rodapé da grid.

Veja como fica o código para totalização :

   68     Private Sub dg_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemDataBound

   69 

   70 

   71         If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

   72 

   73 

   74             Dim lbl As Label

   75             lbl = e.Item.FindControl("lblestoque")

   76             total += lbl.Text

   77         ElseIf e.Item.ItemType = ListItemType.Footer Then

   78 

   79 

   80             Dim lbl As Label

   81             lbl = e.Item.FindControl("lblTGeral")

   82             lbl.Text = "Total : " & String.Format("{0:C}", total)

   83         End If

   84     End Sub

Tomamos novamente o cuidado de verificar o tipo da linha, itemType. Nas linhas de dados fazemos a soma do total, ao chegar ao rodapé exibimos o total geral.

Não esqueça que para o rodapé aparecer é necessário habilitar a exibição do rodapé através do PropertyBuilder da DataGrid

Agrupando as informações por categoria de produto

Agrupamentos de dados em geral podem ser tarefas bem complexas. Mas se utilizarmos os recursos oferecidos pela base de dados então o trabalho no lado client será realmente só de layout.

Farei os exemplos com base em um banco SQL Server. Para outros bancos você deve buscar recursos equivalentes. Vamos então montar passo-a-passo a query SQL que precisaremos utilizar para agrupar nossos dados por categoria e dessa forma fazer com que a DataGrid mostre uma totalização por categoria.

Primeiramente, nossa query inicial :

select a.productid,productname, unitprice, unitsinstock,
unitprice * unitsinstock as total, categoryname
from products a inner join
categories b on a.categoryid=b.categoryid

Como pode obsrevar, já passamos o total para a query, para que seja calculado. Agora precisamos adicionar o agrupamento :

select a.productid,productname, unitprice, unitsinstock,
sum(unitprice * unitsinstock) as total, categoryname
from products a inner join
categories b on a.categoryid=b.categoryid
group by categoryname

Como você vê, essa query não roda. Os campos na lista de campos da query não atendem as regras do agrupamento. Simplesmente não vai rodar, a menos que utilizemos alguns truques pouco ortodoxos :

select a.productid,max(productname), max(unitprice), max(unitsinstock),
sum(unitprice * unitsinstock) as total, categoryname
from products a inner join
categories b on a.categoryid=b.categoryid
group by categoryname,productid

Como o 2o campo inserido no agrupamento é o productID, a aplicação do MAX nos campos da query não afeta em nada o resultado e agora a query roda. Precisamos então obter os totais por categoria :

select a.productid, max(productname), max(unitprice) as unitPrice,max(unitsinstock) as unitsInStock,
sum(unitprice*unitsinstock) as total,
categoryname
from products a
inner join categories b
on a.categoryid=b.categoryid
group by categoryname,productid
with rollup

O "With rollup" adiciona totais pelo penultimo item do agrupamento, neste caso CategoryName, exatamente o que desejamos. Mas como você poderá observar no resultado, temos pouca indicação de quais são as linhas de totais. Vamos então utilizar alguns campos para marcar essas linhas :

select a.productid, max(productname) as Productname, max(unitprice) as unitPrice,max(unitsinstock) as unitsInStock,
sum(unitprice*unitsinstock) as total,
categoryname,
grouping(categoryname) as totGeral,grouping(productid) as totCategoria
from products a
inner join categories b
on a.categoryid=b.categoryid
group by categoryname,productid
with rollup

As duas colunas adicionais, criadas com a função Grouping, resultam em uma marca (0/1) indicando se aquele registro é ou não um total. Coloquei os titulos de forma adequada com a indicação.

Feito isso passamos para o ASP.NET. Como os totais estão todos sendo gerados na base de dados não precisaremos mais do cálculo que fizemos um pouco antes neste artigo. Também precisaremos corrigir a coluna do total em estoque.

Se simplesmente trocarmos a query do Adapter, gerarmos novamente o dataSet e corrigirmos as colunas na DataGrid já veremos um resultado, apesar do layout não ser nada agradável.

O nosso problema então fica sendo corrigir o layout e, para isso, as linhas de totais estão devidamente demarcadas. Assim sendo no itemDataBound podemos procurar pelas linhas de totais e alterar seu layout.

Alterar como ?

Precisará ser uma alteração radical : Retirar 3 das 5 colunas que temos, pois não precisaremos mais delas e fazer com que a 2a coluna ganhe um colSpan=3 para ocupar o espaço que irá sobrar, e a 1a um colSpan=2, só então preencher a 1a e 2a coluna com os dados.

Sim, é isso que vamos ver : Realmente podemos fazer mudanças radicais como essa no trabalho com uma DataGrid.

   69     Private Sub dg_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemDataBound

   70 

   71 

   72         If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then

   73 

   74 

   75             If e.Item.DataItem("totcategoria") = 1 Then

   76 

   77                 'Alteração da disposição das células

   78                 'Você percebeu por que os índices estão ao contrário ?

   79                 e.Item.Cells.RemoveAt(4)

   80                 e.Item.Cells.RemoveAt(3)

   81                 e.Item.Cells.RemoveAt(2)

   82                 e.Item.Cells(1).ColumnSpan = 4

   83                 e.Item.Cells(0).ColumnSpan = 2

   84 

   85                 'Correção do alinhamento

   86                 e.Item.Cells(1).HorizontalAlign = HorizontalAlign.Right

   87 

   88 

   89                 If e.Item.DataItem("totgeral") = 0 Then

   90                     'Destaque para a linha

   91                     e.Item.BackColor = Color.LightBlue

   92 

   93                     'Inserção dos dados

   94                     e.Item.Cells(0).Text = "Categoria : " & e.Item.DataItem("categoryname")

   95 

   96 

   97                     e.Item.Cells(1).Text = String.Format("{0:C}", e.Item.DataItem("total"))

   98 

   99 

  100                 Else

  101                     'Destaque para a linha

  102                     e.Item.BackColor = Color.LightGreen

  103 

  104                     'Inserção dos dados

  105                     e.Item.Cells(0).Text = "Total Geral " & e.Item.DataItem("categoryname")

  106 

  107 

  108                     e.Item.Cells(1).Text = String.Format("{0:C}", e.Item.DataItem("total"))

  109 

  110 

  111                 End If

  112 

  113             End If

  114         End If

  115     End Sub




Envie seus comentários sobre este artigo

Nome :

E-mail :

Comentários :


Avise-me quando houverem novos comentários nesta página

Veja abaixo os comentários já enviados :

Nome : Pablo E-Mail : pabloalencar@gmail.com
Olá Dennis,

Tenho uma dúvida. Eu posso estipular o tempo do Tooltip no Label do Grid.?
Agradeço desde já.
Nome : Elison Silva E-Mail : elison_r@msn.com
Opa, artigo muito bem escrito e me ajudou bastante,

está de parabens!!!
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : -1'
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
1
Nome : 1 E-Mail : 1
-1'
Nome : -1' E-Mail : 1
1
Nome : 1 E-Mail : 1
1