Depois de várias sugestões e dúvidas que vejo nos Newsgroups, decidi escrever este artigo, que tem a finalidade de explicar passo à passo como criar um controle DataGrid do ASP.NET 1.x em tempo de execução. Particularmente eu nunca precisei disto em minhas experiências no trabalho, mas vejo constantemente o pessoal utilizá-los. A idéia basicamente será a construção de um DataGrid e suas colunas, onde teremos:
- 2 BoundColumns: São as colunas que serão apresentadas ao usuário, contendo os valores vindos de uma base de dados qualquer.
- 2 ButtonColumns: Essas representarão os comandos de seleção e de exclusão que o DataGrid terá.
- 1 EditCommandColumn: Esta tem a finalidade de dispor os controles de edição e atualização dos registros que estão visíveis no DataGrid.
- 1 TemplateColumn: Este tipo de coluna permite-nos cria-la de forma customizada, onde podemos colocar o controle que quisermos. Para o exemplo, adicionaremos um DropDownList nos itens do DataGrid.
Baseando-se nas colunas acima, já dá para ter uma idéia de como e onde pretendemos chegar com este DataGrid em tempo de execução. A imagem abaixo mostra-nos o resultado final:
|

|
| Figura 1 - Resultado final do DataGrid. |
Páginas e seus membros
Inicialmente precisamos declarar um objeto do tipo DataGrid, que será o controle que utilizaremos por toda a página. Ele representará o DataGrid como se o mesmo fosse arrastado da ToolBox do Visual Studio .NET para o WebForm. Além do mesmo, vamos declarar a nível de escopo de página, variáveis constantes do tipo String, que serão responsáveis por armazenar a String de conexão com a base de dados e as querys (inclusive com seus parâmetros) que serão executadas no decorrer da página e em seus devidos momentos. O código abaixo ilustra as declarações:
private DataGrid _dg;
private const string CONNECTION_STRING = "CONNECTION_STRING";
private const string UPDATE_QUERY =
"UPDATE Categories SET CategoryName = @Name, Description = @Desc, State = @State WHERE CategoryID = @ID";
private const string DELETE_QUERY = "DELETE FROM Categories WHERE CategoryID = @ID";
private const string SELECT_QUERY = "SELECT * FROM Categories";
|
O evento Page_Init Neste evento, que ocorre antes do evento
Load do WebForm, vamos criar a instância do controle DataGrid, que já o temos declarado (
_dg). Em seguinda, invocaremos a função
ConfigDataGrid que será responsável por configurar as propriedades do controle DataGrid e, por fim, adicionamos o controle DataGrid na coleção de controles do WebForm. Lembrando que, temos que primeiramente procurar pelo
container de controles do WebForm que armazenará o controle DataGrid, ou seja, todos os controles devem estar entre as tags <form>...</form>. Abaixo visualizamos o evento já na íntegra codificado:
override protected void OnInit(EventArgs e)
{
this._dg = new DataGrid();
this.ConfigDataGrid();
this.FindControl("Form1").Controls.Add(this._dg);
InitializeComponent();
base.OnInit(e);
}
|
Configurando o DataGrid Esta seção de configuração do DataGrid deve sempre ser executada, ou seja, sendo um
PostBack ou não e, justamente por isso que devemos executar dentro do evento
Page_Init, pois ele será sempre executado.
Veremos dentro deste procedimento a configuração das propriedades essenciais do DataGrid, tais como:
AutoGenerateColumns,
DataKeyField,
AllowSorting e
SelectedItemStyle.BackColor. A primeira,
AutoGenerateColumns, recebe um valor booleano (
True ou
False) indicando se as colunas serão criadas automaticamente de acordo com a fonte de dados. Neste caso, ela será definida como
False, pois vamos criá-las manualmente. Já a propriedade
DataKeyField, recebe uma
String contendo o nome da coluna que é chave (ID) do registro. Isso será utilizado para quando precisarmos executar as
queries de
Update e
Delete e, veremos abaixo como recuperá-lo. Ao definir a propriedade AllowSorting para
True, o DataGrid habilita o
Header em formato de
HyperLink para a ordenação dos registros. Já a última propriedade que descrevemos anteriormente,
SelectedItemStyle.BackColor, será onde iremos definir qual a cor da linha que o item ficará quando o usuário selecioná-lo. Podemos percebê-la na Figura 1, onde a linha selecionada está na cor azul.
Ainda dentro deste mesmo procedimento,
ConfigDataGrid, chamamos mais dois métodos:
GenerateColumns e
AssignEvents, qual veremos mais detalhadamente um pouco adiante. O código abaixo mostra a versão final do procedimento
ConfigDataGrid:
private void ConfigDataGrid(){
this._dg.AutoGenerateColumns = false;
this._dg.DataKeyField = "CategoryID";
this._dg.AllowSorting = true;
this._dg.SelectedItemStyle.BackColor = Color.LightBlue;
this.GenerateColumns();
this.AssignEvents();
}
|
Depois destas principais propriedades configuradas, vamos analisar umas das partes mais interessantes do DataGrid, que trata-se da criação e configuração das colunas do mesmo. Como já vimos um pouco acima, iremos criar os seguintes tipos de colunas:
BoundColumn,
ButtonColumn,
EditCommandColumn e
TemplateColumn, quais também já vimos cada uma de suas utilidades acima. Estas não tem nada especial em sua criação. Todas consistem em instanciá-las, configurar algumas propriedades e, finalmente, adicionar na coleção de colunas do DataGrid. A única que merece uma atenção especial, é a
TemplateColumn, que necessita a criação de uma classe que implemente a interface
ITemplate. Esta interface define um método chamado
InstantiateIn, qual é utilizado para criar e popular controles que são declarados em uma seção
Template no arquivo ASPX. Abaixo veremos apenas a criação e configuração das colunas do DataGrid:
private void GenerateColumns(){
ButtonColumn sel = new ButtonColumn();
sel.ButtonType = ButtonColumnType.LinkButton;
sel.CommandName = "Select";
sel.Text = "Selecionar";
this._dg.Columns.Add(sel);
ButtonColumn delete = new ButtonColumn();
delete.CommandName = "Delete";
delete.ButtonType = ButtonColumnType.LinkButton;
delete.Text = "X";
this._dg.Columns.Add(delete);
EditCommandColumn edit = new EditCommandColumn();
edit.EditText = "Alterar";
edit.CancelText = "Cancelar";
edit.UpdateText = "Atualizar";
this._dg.Columns.Add(edit);
BoundColumn bc1 = new BoundColumn();
bc1.DataField = "CategoryName";
bc1.HeaderText = "Nome";
bc1.SortExpression = "CategoryName";
this._dg.Columns.Add(bc1);
BoundColumn bc2 = new BoundColumn();
bc2.DataField = "Description";
bc2.HeaderText = "Descrição";
bc2.SortExpression = "Description";
this._dg.Columns.Add(bc2);
TemplateColumn template = new TemplateColumn();
template.ItemTemplate = new DDLTemplate();
this._dg.Columns.Add(template);
}
|
É importante dizer que, a coluna do tipo
BoundColumn fornece duas propriedades importantes chamadas
DataField e
SortExpression onde a primeira corresponde ao campo da fonte de dados que será exibido e é retornado pela query de seleção de registros. Já o segundo, definimos uma
String que será utilizada para enviar para a query de seleção fazer a ordenação através do evento
SortCommand. Por fim, a coluna do tipo
TemplateColumn, recebe uma instância da classe
DDLTemplate, qual também criamos, populamos e adicionamos um controle do tipo DropDownList:
class DDLTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
DropDownList ddl = new DropDownList();
ddl.ID = "State";
ddl.Items.Add(new ListItem("RJ", "RJ"));
ddl.Items.Add(new ListItem("SC", "SC"));
ddl.Items.Add(new ListItem("SP", "SP"));
container.Controls.Add(ddl);
}
}
|
Nota: A classe
TemplateColumn nos fornece várias propriedades interessantes, entre elas:
EditItemTemplate,
FooterTemplate,
HeaderTemplate e
ItemTemplate. Com estas propriedades podemos definir um
Template para cada seção, ou seja, no caso do exemplo deste artigo, estamos atribuindo um controle
DropDownList no
ItemTemplate desta
TemplateColumn. Se por acaso, desejarmos atribuir um controle, ou até mesmo esse
DropDownList no
Header do DataGrid, basta criarmos uma nova instância de uma classe que implemente a interface
ITemplate e adicionarmos na propriedade
HeaderTemplate. O mesmo vale para
EditItemTemplate ou
FooterTemplate.
A configuração do DataGrid está finalizada, pois já definimos todas as propriedades e as colunas necessárias. Agora, o que falta é a criação dos eventos que o DataGrid irá ter e executar. Sendo eles:
- EditCommand: Disparado sempre quando desejarmos colocar um registro em modo de edição.
- CancelCommand: Cancela a edição do registro, não efetuando as possíveis alterações na base de dados.
- UpdateCommand: Atualiza o registro no base de dados.
- DeleteCommand: Exclui o registro da base de dados.
- ItemDataBound: Disparado sempre quando um novo registro é adicionado no DataGrid. Este evento ocorre quando efetuamos o DataBind no controle DataGrid.
- SelectedIndexChanged: É executado quando selecionamos um determinado registro no Datagrid. É disparado quando clicamos no botão "Selecionar", qual criamos através de um ButtonColumn.
- SortCommand: Disparado quando o usuário clicar em um dos HyperLinks do Header do DataGrid para efetuar a ordenação.
Como não estamos arrastando o DataGrid da ToolBox do Visual Studio .NET para o WebForm, os eventos devem ser criados manualmente, ou seja, para cada um desses eventos, obrigatoriamente devemos criar um procedimento para ser executado quando a ação ocorrer. Vale lembrar que, cada um destes procedimentos devem ter a mesma assinatura do delegate já definido pela estrutura do ASP.NET. Veremos:
- EditCommand: Object, DataGridCommandEventArgs.
- CancelCommand: Object, DataGridCommandEventArgs.
- UpdateCommand: Object, DataGridCommandEventArgs.
- DeleteCommand: Object, DataGridCommandEventArgs.
- ItemDataBound: Object, DataGridItemEventArgs.
- SelectedIndexChanged: Object, EventArgs.
- SortCommand: Object, DataGridSortCommandEventArgs.
Antes de entrarmos detalhadamente em cada um destes procedimentos, veremos como "assinar" cada um deles. Em Visual Basic .NET, utilizamos a keyword AddHandler em conjunto com a AddressOf. Já no Visual C#, criamos uma instância do delegate que atende aquele comando. O código abaixo mostra como realizar esse processo:
private void AssignEvents(){
this._dg.EditCommand += new DataGridCommandEventHandler(this.DataGrid_Edit);
this._dg.CancelCommand += new DataGridCommandEventHandler(this.DataGrid_Cancel);
this._dg.UpdateCommand += new DataGridCommandEventHandler(this.DataGrid_Update);
this._dg.DeleteCommand += new DataGridCommandEventHandler(this.DataGrid_Delete);
this._dg.ItemDataBound += new DataGridItemEventHandler(this.DataGrid_ItemDataBound);
this._dg.SelectedIndexChanged += new EventHandler(this.DataGrid_SelectIndexChanged);
this._dg.SortCommand += new DataGridSortCommandEventHandler(this.DataGrid_Sort);
}
|
Evento Load e Carga do DataGrid Até o presente momento fizemos tudo o que o Visual Studio .NET faria por nós se estivessemos utilizando o
designer para a criação do controle. A partir de agora, começaremos a escrever códigos independentemente se estivermos ou não criando o DataGrid em tempo de execução. Primeiramente veremos o evento
Load do WebForm, que deveremos carregar o DataGrid somente se não for PostBack:
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
this.BindDataGrid();
}
}
|
Nota: Muitos acreditam e colocam a criação do DataGrid neste evento e dentro desta condicional que verifica se é ou não
PostBack. Com isso, o controle somente será criado na primeira execução da página, ou seja, se clicar no botão de "Alterar", o DataGrid irá sumir e, não é este o comportamento que esperamos do mesmo. Volto a dizer: a criação deve acontecer sempre, independentemente de ser ou não
PostBack.
Notem que invocamos uma função chamada
BindDataGrid, qual é responsável por resgatar os dados da base de dados e preencher o DataGrid. Criamos uma função para isso justamente porque precisamos disso por todo o código, ou seja, quando acontecer uma atualização ou exclusão de dados, temos que novamente invocar este procedimento para sempre preencher o DataGrid com os dados mais atuais. Como o artigo é baseado em SQL Server, estarei utilizando o
Provider System.Data.SqlClient:
private void BindDataGrid(){
this.BindDataGrid(string.Empty);
}
private void BindDataGrid(string sort){
SqlConnection conn = new SqlConnection(CONNECTION_STRING);
string query = SELECT_QUERY;
if(sort != string.Empty)
query += " ORDER BY " + sort + " ASC";
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader dr = null;
try{
conn.Open();
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
this._dg.DataSource = dr;
this._dg.DataBind();
}finally{
if(dr != null) dr.Close();
}
}
|
Como podemos reparar no código acima, criamos dois métodos sobrecarregados, onde em um desses métodos, recebe uma
String que corresponde à coluna que serão ordenados os registros, qual será sempre chamado no evento
SortCommand do DataGrid. Definimos também a conexão com a base de dados, e através de um objeto do tipo
SqlCommand, passamos a query a ser executada, que está definida na constante
SELECT_QUERY e, retornamos um objeto do tipo
SqlDataReader que, conseqüentemente, definimos na propriedade
DataSource do DataGrid.
Codificando os Eventos Depois dos eventos já assinados, ou seja, atribuímos a cada um deles o procedimento a ser executado quando a ação acontecer, devemos neste momento codificar cada um deles. Vamos detalhar cada um dos eventos do DataGrid começando pelo evento
EditCommand. Este evento, será disparado quando o usuário clicar no botão "Alterar" do DataGrid. Neste momento, devemos definir a propriedade
EditItemIndex com o índice da linha que será editada. Conseguímos recuperar o índice através do "e" que vem como parâmetro, qual nos fornece uma propriedade chamada
ItemIndex e, em seguida, chamamos novamente o método
BindDataGrid para carregar o DataGrid, mas agora, o mesmo já será apresentado com o registro que o usuário requisitou em modo de edição. O código e a figura abaixo ilustram esse processo:
private void DataGrid_Edit(object sender, DataGridCommandEventArgs e)
{
this._dg.EditItemIndex = e.Item.ItemIndex;
this.BindDataGrid();
}
|
|

|
| Figura 2 - DataGrid em modo de edição. |
Na seqüência veremos o evento CancelCommand, que tem a finalidade de cancelar o modo de edição, descartando as possíves alterações que o usuário tenha feito no registro. É basicamente o mesmo que fizemos no evento acima, com a exceção de definir a propriedade EditItemIndex do DataGrid para -1, que indica que nenhum registro deverá ficar em modo de edição:
private void DataGrid_Cancel(object sender, DataGridCommandEventArgs e)
{
this._dg.EditItemIndex = -1;
this.BindDataGrid();
}
|
Para finalizar os eventos correspondentes à edição de registro, vamos analisar o evento
UpdateCommand, qual será disparado quando o usuário clicar no botão "Atualizar" do DataGrid. Neste momento devemos recuperar o novo conteúdo que o usuário digitou e submetermos para a base de dados através de objetos que estão contidos dentro do Namespace
SqlClient.
Antes de vermos como isso é feito, precisamos entender como devemos acessar estes controles (
TextBox e o
DropDownList que está na
TemplateColumn). As formas de acessá-los são diferentes, ou seja, quando formos resgatar o conteúdo dos
TextBox, que correspondem as colunas (
BoundColumn) que estamos editando, temos que navegar entre a coleção de controles através dos índices até chegarmos ao controle desejado, pois através do método
FindControl, "não conseguimos", já que estamos assumindo que não transformamos as colunas
BoundColumn em
TemplateColumn, para assim sabermos o ID que cada controle ganhou.
Já para acessar o controle que está em uma
TemplateColumn, podemos tanto navegar pelo índice dos controles, como utilizar o método
FindControl, que é bem mais fácil de utilizar, pois sabemos (e o definimos dentro do método
InstantiateIn da classe
DDLTemplate) o ID do controle
DropDownList que temos nesta coluna.
Aproveito essa oportunidade para explicar como recuperar o índice (ID) da linha que está sendo atualizada: lembram da propriedade
DataKeyField? Ela armazena para cada linha/registro do DataGrid o ID (o valor da coluna que definimos) e, podendo agora ser recuperado para embutí-lo na query de
Update, que está armazenada na constante
UPDATE_QUERY. O DataGrid fornece uma propriedade chamada
DataKeys que, expõe uma coleção de chaves, onde dado um índice, ele retorna o valor correspondente desta linha. Criamos os parâmetros, com o objeto do tipo
SqlParameter, passando os valores que recuperamos dos controles de dentro do DataGrid e, anexamos na coleção de parâmetros do objeto
SqlCommand. Finalmente abrimos a conexão com a base de dados e, através do método
ExecuteNonQuery do objeto
SqlCommand, executamos a query na base dados, atualizando o registro. O código abaixo exemplifica:
private void DataGrid_Update(object sender, DataGridCommandEventArgs e){
string name = ((TextBox)e.Item.Controls[3].Controls[0]).Text;
string description = ((TextBox)e.Item.Controls[4].Controls[0]).Text;
string state = ((DropDownList)e.Item.FindControl("State")).SelectedValue;
int id = Convert.ToInt32(this._dg.DataKeys[e.Item.ItemIndex]);
SqlConnection conn = new SqlConnection(CONNECTION_STRING);
SqlCommand cmd = new SqlCommand(UPDATE_QUERY, conn);
cmd.Parameters.Add(new SqlParameter("@Name", SqlDbType.VarChar)).Value = name;
cmd.Parameters.Add(new SqlParameter("@Desc", SqlDbType.VarChar)).Value = description;
cmd.Parameters.Add(new SqlParameter("@State", SqlDbType.VarChar)).Value = state;
cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = id;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
finally
{
if(conn != null) conn.Close();
this._dg.EditItemIndex = -1;
this.BindDataGrid();
}
}
|
Dentro do bloco
Finally fechamos a conexão com a base de dados, voltamos a definir a propriedade
EditItemIndex para -1 e, por fim, invocamos o procedimento
BindDataGrid para recarregar o DataGrid com os novos dados. Eu omiti o bloco
Catch apenas para economizar espaço, mas isso jamais deverá acontecer em produção.
O próximo evento a analisarmos é o
DeleteCommand, qual será disparado quando o usuário clicar no "X" do DataGrid, que corresponderá a exclusão do registro. O código é bem parecido com o qual vimos um pouco acima, no evento
UpdateCommand, ou seja, devemos recuperar o ID do registro através da coleção de
DataKeys do DataGrid para podermos criar o parâmetro para o objeto
SqlCommand, definindo como
Value deste parâmetro, o valor que iremos recuperar do
DataKeyField. Depois disso, abrimos a conexão com a base de dados, e executamos a query de exclusão que está armazenada na constante
DELETE_QUERY. Vejamos:
private void DataGrid_Delete(object sender, DataGridCommandEventArgs e){
int id = Convert.ToInt32(this._dg.DataKeys[e.Item.ItemIndex]);
SqlConnection conn = new SqlConnection(CONNECTION_STRING);
SqlCommand cmd = new SqlCommand(DELETE_QUERY, conn);
cmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = id;
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
finally
{
if(conn != null) conn.Close();
this.BindDataGrid();
}
}
|
Da mesma forma que o evento
UpdateCommand, no bloco
Finally fechamos a conexão com a base de dados e chamamos o procedimento
BindDataGrid para recarregar novamente o DataGrid já com os novos dados.
Ainda nos eventos em que o usuário dispara, falta para completar a lista o evento
SelectedIndexChanged. Este evento é disparado sempre quando o usuário clica no botão "Selecionar" do DataGrid. É sempre interessante colorirmos a linha em questão para que o usuário consiga identificar qual dos registros é que está selecionado. É justamente por isso que definimos a propriedade
SelectedItemStyle.BackColor do DataGrid com uma cor (definida através da estrutura
System.Drawing.Color) diferente da cor padrão dos Itens. Veremos abaixo este evento já codificado:
private void DataGrid_SelectIndexChanged(object sender, EventArgs e)
{
DataGridItem item = this._dg.SelectedItem;
this.Label1.Text = "Item selecionado: " + item.Cells[3].Text;
}
|
Através da propriedade
SelectedItem do DataGrid, recuperamos uma instância de um objeto do tipo
DataGridItem (toda linha do DataGrid é um objeto do tipo
DataGridItem) e assim, temos acesso a todas as informações da linha selecionada pelo usuário. Com isso, atribuímos à propriedade
Text de um controle
Label, o valor contido na
BoundColumn, que no caso do exemplo deste artigo, é o nome da Categoria. Muitas pessoas querem que, quando o usuário selecione um item do DataGrid, os demais dados sejam apresentados em um outro Datagrid ou mesmo em outros controles do WebForm, gerando assim uma espécie de
DetailsView do registro. O evento
SelectIndexChanged é o ideal para este cenário, podendo adotar a mesma técnica que expliquei aqui.
Ainda temos o evento
SortCommand, qual será disparado quando o usuário clicar em algum dois
HyperLinks do
Header do DataGrid. Dentro deste evento, chamaremos o procedimento
BindDataGrid passando como parâmetro o valor da propriedade
SortExpression que vem como parâmetro para o evento. Com isso, uma nova query será criada e, o DataGrid será carregado com os registros já ordenados de acordo com o que o usuário requisitou. O código abaixo mostra-nos a chamada à este método sobrecarregado dentro do evento
SortCommand:
private void DataGrid_Sort(object sender, DataGridSortCommandEventArgs e)
{
this.BindDataGrid(e.SortExpression);
}
|
Para finalizarmos os eventos, falta explicar o evento
ItemDataBound. Este por sua vez, é sempre disparado a cada novo registro que está sendo incluído no DataGrid através do
DataBind, ou seja, ocorre automaticamente quando chamamos o método
DataBind do DataGrid. Dentro dele, conseguimos interceptar os valores e controles que serão exibidos pelo DataGrid antes de serem renderizados para o cliente. Neste momento, é que vamos adicionar no coleção de atributos do controle
LinkButton de exclusão um código Javascript que será responsável pela confirmação de exclusão do registro. É também aqui que iremos atribuir o valor da coluna "Estado" proveniente da base de dados à propriedade
SelectedValue do controle
DropDownList. Antes de nos aprofundarmos no evento, vamos visualizar o evento já codificado:
private void DataGrid_ItemDataBound(object sender, DataGridItemEventArgs e){
if(e.Item.ItemType == ListItemType.AlternatingItem ||
e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.SelectedItem)
{
this.SetJavaScript(e.Item);
DropDownList ddl = (DropDownList)e.Item.FindControl("State");
ddl.SelectedValue = ((DbDataRecord)e.Item.DataItem)["State"].ToString();
ddl.Enabled = false;
}
else if(e.Item.ItemType == ListItemType.EditItem)
{
this.SetJavaScript(e.Item);
((DropDownList)e.Item.FindControl("State")).SelectedValue =
((DbDataRecord)e.Item.DataItem)["State"].ToString();
}
}
private void SetJavaScript(DataGridItem item){
LinkButton lnk = (LinkButton)item.Controls[1].Controls[0];
lnk.Attributes.Add("onClick",
@"return confirm (""Tem certeza que deseja excluir o produto?"");");
}
|
Antes de qualquer coisa, algumas condições devem ser verificadas para que não ocorra nenhum erro. A começar que devemos verificar o tipo da linha que está sendo inserida no controle através do Enumerador
ListItemType. Os dados em suas versões normais, estão sempre nas linhas do tipo
Item,
AlternatingItem ou
SelectedItem e, para certificarmos que não estamos inserindo ou tentando acessar um controle que não exista, devemos fazer esta verificação, mesmo porque muitas vezes não utilizamos as linhas do DataGrid que são do tipo
Header e
Footer para inserir os dados da base de dados, mas sim para uma sumarizar uma determinada coluna, ou algo do tipo, que no caso de um simples
DataBind devem ser desconsideradas.
No exemplo do artigo, podemos acessar o controle
DropDownList em quatro momentos, pois não temos ele somente quando a linha entrar em modo de edição, mas também quando os registros estão sendo apresentados em sua forma normal e quando a linha estiver selecionada. A verificação do tipo da linha aqui é para que quando o usuário estiver com o registro em modo normal, o controle
DropDownList seja apresentado, mas ele não poderá ser acessado, ou seja, define-se a propriedade
Enabled do mesmo para
False e, ao contrário, quando estiver em modo de edição, o usuário poderá acessá-lo para poder definir um "Estado" diferente, se assim desejar.
Também criamos um procedimento auxiliar chamado
SetJavaScriptConfig, qual será responsável por atribuir na coleção de atributos do LinkButton responsável pelo Exclusão ("X"), o código
JavaScript de confirmação da exclusão do registro. A imagem abaixo exibe o
JavaScript em execução:
|

|
| Figura 3 - Confirmação de exclusão em funcionamento. |
Paginação de dados
Para realizar a paginação dos dados, o procedimento é o mesmo: cria-se o procedimento e o define para ser executado quando o delegate PageIndexChanged for disparado. A única observação é que você não pode atribuir diretamente um objeto do tipo DataReader à propriedade DataSource do DataGrid quando for efetuar a paginação, porque através do DataReader não se consegue saber quantos registros serão retornardos, informação qual é necessária para que o DataGrid crie a infra-estrutura e disponibilize a paginação ao usuário. Como isso trata-se de algo um pouco mais complexo e mais detalhes do que vimos nesta pequena descrição, deixaremos esse tema para talvez um próximo artigo.
CONCLUSÃO: Como pudemos analisar no decorrer deste artigo, não temos muitos segredos em criar um controle DataGrid em tempo de execução. O que precisamos mesmo é nos atentar nos pequenos detalhes, como por exemplo a criação do DataGrid sendo ou não PostBack que, se não fizermos desta forma, o resultado apresentado não será o esperado. Claro que grande parte do que fizemos aqui via código, ao arrastar o controle DataGrid da ToolBox do Visual Studio .NET, parte deste trabalho/código seria realizado internamente pela IDE. De qualquer forma, fica aqui registrado como devemos proceder para a criação do controle DataGrid em tempo de execução para que se algum dia for preciso recorrer à esta forma, está aqui exemplificado.
DataGridRuntime.zip (48.40 kb)