Já vi muitas perguntas iguais ou semelhantes em fóruns: Como coloco caixas de seleção, caixas de texto, etc. em cada linha do meu DataGrid? Como atualizar seus valores? A resposta é bem simples e neste artigo vou mostrar como fazer isso.
Todos sabemos que o DataGrid é uma ferramenta muito poderosa. Na minha experiência, mais de 90% das vezes, o DataGrid é usado para exibir dados e possivelmente editá-los uma linha por vez. Às vezes, pode ser necessário editar várias linhas ou até mesmo todos os dados de uma vez. Um exemplo prático seria em um aplicativo que vende itens online, onde os clientes podem querer alterar um ou mais itens de sua cesta por vez, clicando nas caixas de seleção para remover os itens que não desejam.
Conceito
Neste exemplo, escrevi um WebForm simples para gerenciar uma lista de contatos armazenada em XML. O requisito é muito simples: ter a capacidade de adicionar novos contatos, editar/excluir contatos existentes. Os usuários podem modificar ou excluir vários contatos de uma vez, e também permito que os usuários classifiquem a grade de dados por colunas de sua escolha.
Meus exemplos são escritos em C#. Se você preferir a versão VB desses códigos, o código está disponível em ambos os formatos no arquivo para download.
O arquivo de dados XML no
exemploContacts.xml
é muito simples e intuitivo.Como é muito simples, não criei um plano.
<?xml version="1.0" autônomo="sim"?>
<Contatos>
<Contato>
<E-mail>meuendereç[email protected]</E-mail>
<Nome>João</Nome>
<Sobrenome>Doe</Sobrenome>
</Contato>
<Contato>
<E-mail>seuendereç[email protected]</E-mail>
<Nome>Jane</Nome>
<Sobrenome>Doe</Sobrenome>
</Contato>
</Contacts>
ContactList.aspx
Configurar um WebForm é muito simples. Coloquei um novo DataGrid em meu formulário e configurei-o para ter 4 colunas, com a primeira coluna contendo caixas de seleção para exclusão de contatos. Você notará que a principal coisa que fiz aqui foi criar cada coluna como uma coluna de modelo (TemplateColumn). Isso me permite colocar objetos de caixa de texto e caixa de seleção no modelo de dados (ItemTemplate). Este é um truque para exibir algo diferente de texto em cada linha da grade. Além disso, você notará que eu uso um FooterTemplate para tornar a criação de novos contatos fácil e intuitiva.
Também incluí um LinkButton para salvar modificações e exclusões feitas pelo usuário. Mas não é usado para adicionar novos contatos. A operação de adição de novos contatos é completada pelo botão de link (LinkButton) no modelo de rodapé da última coluna.
<asp:datagrid id="dgContacts" runat="server" ShowFooter="True" AllowSorting="True" Forefont color="Black" GridLines="None" CellPadding="2" Backfont color="LightGoldenrodYellow" BorderWidth="1px " Borderfont color="Tan" Width="499px" AutoGenerateColumns="False" DataKeyField="Email">
<SelectedItemStyle Forefont color="GhostWhite" Backfont color="DarkSlateBlue"></SelectedItemStyle>
<AlternatingItemStyle Backfont color="PaleGoldenrod"></AlternatingItemStyle>
<HeaderStyle Font-Bold="True" Backfont color="Tan"></HeaderStyle>
<FooterStyle Backfont color="Tan"></FooterStyle>
<Colunas>
<asp:TemplateColumn SortExpression="Nome" HeaderText="Nome">
<ItemTemplate>
<asp:TextBox id=Primeiro runat="servidor" Width="109px" Text='<%# DataBinder.Eval(Container, "DataItem.FirstName") %>'>
</asp:TextBox>
</ItemTemplate>
<Modelo de rodapé>
<asp:TextBox id="NewFirst" runat="server" Width="109px"></asp:TextBox>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn SortExpression="Sobrenome" HeaderText="Sobrenome">
<ItemTemplate>
<asp:TextBox id=Last runat="server" Width="109px" Text='<%# DataBinder.Eval(Container, "DataItem.LastName") %>'>
</asp:TextBox>
</ItemTemplate>
<Modelo de rodapé>
<asp:TextBox id="NewLast" runat="server" Width="109px"></asp:TextBox>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn SortExpression="E-mail" HeaderText="E-mail">
<ItemTemplate>
<asp:TextBox id=E-mail runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.Email") %>'>
</asp:TextBox>
</ItemTemplate>
<Modelo de rodapé>
<asp:TextBox id="NewEmail" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="Excluir contato">
<ItemStyle HorizontalAlign="Center"></ItemStyle>
<ItemTemplate>
<asp:CheckBox Runat="server" ID="chkDelete"></asp:CheckBox>
</ItemTemplate>
<FooterStyle HorizontalAlign="Center"></FooterStyle>
<Modelo de rodapé>
<asp:LinkButton Runat="servidor" Text="Adicionar" CommandName="Adicionar" ID="Linkbutton1" NAME="Linkbutton1"></asp:LinkButton>
</FooterTemplate>
</asp:TemplateColumn>
</Colunas>
</asp:datagrid>
ContactList.cs
Depois de optar por usar um arquivo XML para acessar os dados, decidi usar um DataSet para acessá-los. Como o objeto DataSet possui métodos ReadXml e WriteXml, essa é uma escolha bastante razoável. O primeiro passo é ler os dados em XML. Como você pode ver no código, criei um membro para lidar com a classificação dos dados.
conjunto de dados privado _dsContacts;
string privada _sSort;
private void Page_Load (remetente do objeto, System.EventArgs e)
{
//Carrega arquivo XML.
_dsContatos = new DataSet();
_dsContacts.ReadXml(Server.MapPath("Contatos.xml"));
DataColumn[] dcPk = {_dsContacts.Tables["Contato"].Colunas["E-mail"]};
_dsContacts.Tables["Contato"].PrimaryKey = dcPk;
if (!Page.IsPostBack )
{
// Se for carregado pela primeira vez, vincula os dados.
BindContatos();
_sSort = "Nome";
}
outro
{
// Caso contrário, leia o estado de classificação do estado de visualização.
_sSort = (string)ViewState["Classificar"];
}
}
Na segunda etapa, criei um método para vincular dados à grade, que incluía lógica de classificação de dados e métodos para leitura de dados do disco.
privado vazio BindContacts()
{
//Salve o estado de classificação para visualizar o estado.
ViewState["Sort"] = _sSort;
// Vincula a grade à visualização de dados classificada.
DataView dv = new DataView(_dsContacts.Tables["Contato"]);
dv.Sort = _sSort;
dgContacts.DataSource = dv;
dgContacts.DataBind();
}
private void SaveContacts()
{
_dsContacts.WriteXml(Server.MapPath("Contatos.xml"));
}
O evento ItemCommand é usado para adicionar novos contatos à lista. Obs: verifiquei se o parâmetro CommandName é Add. Serve para tratar o valor de retorno do botão de link (LinkButton) no template de rodapé (FooterTemplate) da última coluna da grid na página ASPX.
private void dgContacts_ItemCommand (objeto fonte, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
//Adicione novos dados ao conjunto de dados. Aqui eu uso um array para melhorar a eficiência do processamento.
if (e.CommandName == "Adicionar")
{
string[]sContato = {"", "", ""};
sContact[0] = ((TextBox)e.Item.FindControl("NovoEmail")).Text;
sContact[1] = ((TextBox)e.Item.FindControl("NovoPrimeiro")).Text;
sContact[2] = ((TextBox)e.Item.FindControl("NewLast")).Text;
_dsContacts.Tables["Contato"].Rows.Add(sContacts
());
}
BindContatos();
}
Ignorei o código SortCommand porque há muitos outros documentos que discutem a classificação detalhadamente. Se você baixar o código-fonte deste exemplo, ele estará incluído.
Por fim, movi o evento click (onClick) do botão do link (LinkButton) do formulário para aqui. Aqui eu percorro os itens de dados no DataGrid para executar quaisquer operações de exclusão e atualização necessárias.
private void btnUpdate_Click (remetente do objeto, System.EventArgs e)
{
// Loop através de cada item de dados.
foreach (DataGridItem em dgContacts.Items)
{
// Certifique-se de que seja um item de dados e não a parte superior ou inferior da página.
if (di.ItemType == ListItemType.Item || di.ItemType == ListItemType.AlternatingItem)
{
// Obtém a linha atual após a operação de atualização ou exclusão ser executada.
DataRow dr = _dsContacts.Tables["Contact"].Rows.Find(dgContacts.DataKeys[di.ItemIndex]);
// Verifica se uma linha precisa ser excluída.
if (((CheckBox)di.FindControl("chkDelete")).Verificado)
{
_dsContacts.Tables["Contact"].Rows.Remove(dr);//Exclui a linha especificada
}
outro
{
//Atualiza linha de dados.
dr["E-mail"] = ((TextBox)di.FindControl("E-mail")).Text;
dr["Nome"] = ((TextBox)di.FindControl("Primeiro")).Text;
dr["Sobrenome"] = ((TextBox)di.FindControl("Sobrenome")).Text;
}
}
}
//Salve se houver alterações.
se (_dsContacts.HasChanges())
{
SalvarContatos();
}
BindContacts();//ligação
}
Conclusão
Posso encontrar facilmente as células (Cells) de cada DataGridItem no controle através da posição do controle. Existem várias maneiras de fazer isso e tenho certeza de que você encontrará uma maneira melhor de realizar essa tarefa. Como você pode ver, editar toda a grade de dados de uma só vez é muito simples. O mesmo método também pode ser usado para grades paginadas com pequenas modificações