Desenvolvimento - ASP. NET
ASP.NET: Classe para tratamento de DataGrid
Toda vez que trabalhamos com dados em componentes do tipo DataGrid estamos sujeitos à algumas dificuldades. Um exemplo seria quando tentamos remover o último item de uma página do DataGrid e, após recarregar os dados, a página atual do DataGrid passa a ser maior do que o número de páginas existentes, gerando uma exceção.
por Artur Caliendo PradoToda vez que trabalhamos com dados em componentes do tipo DataGridestamos sujeitos à algumasdificuldades. Um exemploseria quando tentamos removero últimoitem de uma página do DataGrid ( imagine uma tabela com 3 itens e 2 itens por página, e excluímos o terceiro item)e, após recarregar os dados,a página atual do DataGridpassa a ser maior do que o número de páginas existentes, gerando uma exceção. Através de uma classe é possível centralizar todas as funçõesa serem utilizadas e evitar a repetição de código para cada DataGrid criado, agilizando a criação de páginas e minimizando os erros de desenvolvimento.
Identificando o problema
O primeiro passo para corrigir os repetitivos erros que ocorremcom os DataGrids é identificar em quais momentos os erros ocorrem.
1. Quando criamos um novo registro;
2. Ao tentar criar um novo registro, a página do DataGrid pode estar cheia, fazendo com que o novo registro apareça na página seguinte. Porém, se a inserção falhar e a execução não for interrompida ou devidamente tratada, o DataGrid, após ser recarregado, tentará manter-se na página nova, mas esta não existirá, uma vez que o dado não foi inserido;
3. Ao excluir o último registro de uma pagina e recarregar os dados do DataGrid.
A princípio estes são os momentos principais onde nosso programa é interrompidocomalguma excessão. Outros erros podem ocorrer mas, criando-se um classe para tratar os DataGrids, qualquer alteração desejada é feita em apenas um lugar, tornando o processo muito mais inteligente.
Implementação
Neste artigo, utilizaremos a linguagem C# .NET.
Crie uma bibilioteca de classes. Para fazer isso, clique com o botão direito do
mouse sobre a soluçãoe escolha "Add", e, em seguida, "New Project".
Procure nos templates o item "Class Library". Dê um nome para a
bibliotecae pressiona "OK". Após criar o projeto, clique com o botão
direito do mouse sobre o projeto e escolha "Add", e "Add New Item". Adicione
uma classe ("Class"), e dê a ela o nome de "ObjGrid.cs". Pronto, já criamos a
classe que irá fazer os tratamentos necessários nos DataGrids.
Para utilizar DataSet e DataGrid na classe ObjGrid.cs, adicione:
using System.Data; using System.Web.UI.WebControls;Crie o seguinte método:
public static void BindGrid(DataSet ds, DataGrid dg) { //Guarda a página em que o DataGrid está antes de ser recarregado. int pos = dg.CurrentPageIndex; //Muda a página atual para a página zero, evitando erros durante o DataBind() dg.CurrentPageIndex = 0; //Atualiza o DataGrid dg.DataSource = ds; dg.DataBind(); //Caso a página em que o DataGrid estava antes de ser recarregado não existir, //deve-se buscar a última página válida. while (pos > dg.PageCount-1 && pos > 0) pos--; //Coloca o Grid em uma página válida. dg.CurrentPageIndex = pos; //Atualiza o DataGrid na página. dg.DataBind(); }
É importante que o método seja estático, para que não seja necessário instanciar
a classe toda vez que um DataGrid sofrer alguma alteração. Porém, nem sempre
usamos um DataSet para preencher DataGrids. Podemos usar outras fontes, como
DataTable ou DataView. Para que a classe fique completa, crie uma sobrecarga
deste método para os tipos que você precisar em seu projeto.
Quando mudamos um DataGrid de páginageralmente esperamosque ele
saia do "modo edição", e não possua mais nenhum item selecionado, uma vez que
estaremos indo para uma página nova. Este, assim como outros métodos criados
neste artigo, são opcionais. Você também deve adaptá-lo às suas necessidades,
se precisar que os DataGrids possuam umcomportamento específico.
public static void TrocaPagina(DataGrid dg, int newPageIndex) { //Garante que nenhum item permanecerá selecionado. dg.SelectedIndex = -1; //Tira o DataGrid do modo edição. dg.EditItemIndex = -1; //Atualiza a página do DataGrid dg.CurrentPageIndex = newPageIndex; }Se desejar, adicione mais um parâmetro ao método (o DataSet, ou qualquer fonte de dados para preenchimento do DataGrid) e chame o método BindGrid antes de terminar o método TrocaPagina, diminuindoa necessidade de criar código repetitivo em suas páginas. Então, o métodoficariaassim:
public static void TrocaPagina(DataGrid dg,int newPageIndex, DataSet ds) { //Garante que nenhum item permanecerá selecionado. dg.SelectedIndex = -1; //Tira o DataGrid do modo edição. dg.EditItemIndex = -1; //Atualiza a página do DataGrid dg.CurrentPageIndex = newPageIndex; //Recarrega os dados. BindGrid(ds, dg); }Adicione os dois métodos a seguir para aumentar a quantidade de opções:
public static bool ModoEdicao(DataGrid dg,DataSet ds, int itemIndex) { bool retorno = false; if (ObjGrid.PodeEditar(dg)) { retorno = true; //Seleciona o item. dg.SelectedIndex = itemIndex; //Coloca o DataGrid em modo edição. dg.EditItemIndex = itemIndex; //Recarrega os dados. BindGrid(ds, dg); } else { retorno = false; } return retorno; }E o método para verificar se um DataGrid já está sendo editado:
public static bool PodeEditar(DataGrid dg) { return (dg.EditItemIndex == -1); }
No método "ModoEdicao" pode ser indesejável chamar o "BindGrid" dentro da
classe. Como dito anteriormente, altere a classe de acordo com as suas
necessidades. Para finalizar, temos o problema da inserção de novos registros.
Aplicações que utilizam muitos DataGrids e fazem as alterações e inserções
diretamente no componente tendem a repetir o mesmo código de inserção para cada
Grid. O ideal é mantermos o método nesta classe, a chamá-lo quando necessário.
Lembre-se que é necessário que o DataSet passado como parâmetro esteja
devidamente preenchido. Utilize outras classes de dados, como o DataTable, se
achar necessário.
public static void NovoRegistro(DataSet ds, DataGrid dg) { int ValorIndex; //Cria uma nova linha para ser inserida no DataSet DataRow novoRegistro = ds.Tables[0].NewRow(); //Inserindo a nova linha no final do DataSet. ds.Tables[0].Rows.InsertAt(novoRegistro,Convert.ToInt16 (ds.Tables[0].Rows.Count.ToString())); //Obtém a posição do novo item, para usar como EditItemIndex. ValorIndex=(ds.Tables[0].Rows.Count %dg.PageSize)-1 ; //Se o DataSet não possuía linhas, devemos prepará-lo para seu primeiro registro. //Esta condição também serve para perceber se a página atual já está cheia de registros,. //Preparando o registro para ser colocado na próxima página. if (ValorIndex == -1) { ValorIndex=Convert.ToInt32 (dg.PageSize)-1; } //Se o registro for o primeiro de uma nova página, temos que resolver um problema. //A propriedade PageCount do DataGrid não está contando com a linha que acabamos de inserir, uma //vez que este dado ainda não faz parte do DataGrid. if ((ds.Tables[0].Rows.Count > 1 )&&(ValorIndex==0)) { dg.CurrentPageIndex = dg.PageCount; } else { dg.CurrentPageIndex = dg.PageCount-1; } //Finalmente, colocamos o DataGrid no modo de edição e carregamos os dados. dg.EditItemIndex = ValorIndex; dg.SelectedIndex = ValorIndex; ObjGrid.BindGrid(ds,dg); }
Mas como usar esta classe? Se você entendeu como ela é feita, já sabe que é muito simples utilizar seus recursos. Abaixo segue um exemplo de utilização da classe, para cada tipo de modificação feita no DataGrid.
Existem duas possibilidades:
1. O DataSet dsCep é armazenado em uma viewState, e pode ser usado em qualquer método.
Isto não é uma boa prática se o DataSet possuir grande quatidade de dados. Então usaremos a opção 2.
2. O método getDataSet() faz uma consulta na base de dados e retorna os dados em um DataSet.
Neste caso, a página fará várias conexões com a base de dados, mas não guardará os dados em ViewStates.
protected void dgCep_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e) { ObjGrid.TrocaPagina(dgCep, e.NewPageIndex, getDataSet()); } protected void dgCep_Edit(Object source, DataGridCommandEventArgs e) { if (!ObjGrid.ModoEdicao(dgCep, getDataSet(), e.Item.ItemIndex)) { lblAviso.Text = "Termine de editar o DataGrid antes de inciar o modo edição."; } } protected void BindGridCep() { ObjGrid.BindGrid(dgCep, getDataSet()); } protected void dgCep_Cancel(Object sender, DataGridCommandEventArgs e) { dgCep.EditItemIndex = -1; dgCep.SelectedIndex = -1; BindGridCep(); }O evento mais complexo, de inserir um novo registro, ficou muito simples. Observe:
private void imgIncluirCep_Click(object sender, System.Web.UI.ImageClickEventArgs e) { if (ObjGrid.PodeEditar(dgCep)) { ObjGrid.NovoRegistro(getDataSet(), dgCep); } }
Ao final dos métodos de Update e de Delete você terá que recarregar o DataGrid. Para isso, chame o método BindGridCep(). Com isso, com certeza você não terá mais problemas de páginas que não existem!
Se desejar, pegue o código pronto aqui .