Criando um DataGrid em Runtime


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)

Publicidade

4 comentários sobre “Criando um DataGrid em Runtime

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s