É muito comum ver DataBinder.Eval em Repeater, DataGrid e DataList, mas muitos não sabem que ele pode causar problemas de performance.
No artigo de hoje vou mostrar algumas alternativas ao DataBinder.Eval
O Eval é um método que usa Reflection em tempo de execução para descobrir o tipo de dado do DataItem. E isso pode causar visível lentidão quando o volume de dados é grande, inclusive a própria Microsoft não recomenda o uso dele devido a sobrecarga.
Mas para pequenos volumes de dados vai bem.
Mas o que acontece na prática?
Imagine um Repeater onde seu DataSource é uma tabela com 10 linhas e 5 colunas. Então você usa Eval para retornar o valor de cada coluna, isso representa 5 chamados a cada linha. Assim no final das 10 linhas você terá chamando o Eval 50 vezes.
Abaixo vou mostrar o uso comum do DataBinder.Eval.
O Eval requer 2 ou 3 argumentos.
1: A própria fonte de dados
2: Nome do campo/coluna
3: Formatação
Exemplos de uso:
Usando somente o Eval, que não é igual ao DataBinder.Eval.
<%# Eval("DataCadastro") %>
Resultado: 05/01/2013 14:27:06
DataBinder.Eval com 2 argumentos - fonte de dados e o campo - neste caso o campo DataCadastro refere-se a propriedade do objeto Pessoa.
<%# DataBinder.Eval(Container.DataItem,"DataCadastro") %>
Resultado: 05/01/2013 14:27:06
DataBinder.Eval com formatação de dados.
<%# DataBinder.Eval(Container.DataItem,"DataCadastro", "{0:D}") %>
Resultado: quarta-feira, 9 de janeiro de 2013
Alternativas ao DataBinder.Eval.
Vou mostrar basicamente 2 alternativas, ambas usando o Container.DataItem, uma no próprio .ASPX e outra no .CS (ItemDataBound).
Container.DataItem é onde estão contidos os dados da posição atual da coleção/lista, ou seja, corresponde a uma linha.
A tipagem do DataItem é determinada pelo tipo de DataSource, então se sua fonte de dados é List<String> o DataItem é string.
Para pegar as propriedades de um objeto, você terá que fazer antes a conversão para o respectivo tipo.
Vendo os exemplos vai ficar melhor de entender.
Uso de Container.DataItem com conversão explícita.
<%# ((Pessoa)Container.DataItem).DataCadastro %>
Container.DataItem com DataSet e DataTable.
<%@ Import Namespace="System.Data" %>
...
<asp:Repeater runat="server" ID="Repeater1">
<ItemTemplate>
<%#((DataRowView)Container.DataItem)["DataCadastro"]%>
</ItemTemplate>
</asp:Repeater>
Mover o Eval para o code behind usando o ItemDataBound
Default.aspx
<asp:Repeater runat="server" ID="Repeater1" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
<asp:Literal ID="litDataCadastro" runat="server" />
</ItemTemplate>
</asp:Repeater>
Default.aspx.cs
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
//Pegar o Container.DataItem e converter para o tipo de dados específico, no meu caso, o tipo é Pessoa.
Pessoa pessoa = (Pessoa)e.Item.DataItem;
//Encontrar o Literal no Repeater
Literal litDataCadastro = (Literal)e.Item.FindControl("litDataCadastro");
//Popular o literal com a data de cadastro já formatada
litDataCadastro.Text = pessoa.DataCadastro.ToString("dd/MM/yyyy");
//Retornará: 05/01/2013
}
}
Faça download do projeto com vários exemplos aqui.