Desenvolvimento - Visual Basic .NET

DataGrid Editável com DropDownList e CheckBox - ASPNET

Neste artigo explicarei como utilizar o Datagrid para editar registros utilizando Template Columns onde usaremos CheckBox e DropDownList.

por Israel Aéce



Neste artigo explicarei como utilizar o Datagrid para editar registros utilizando Template Columns onde usaremos CheckBox e DropDownList.

Para isso temos que criar as tabelas no SQL Server (ou em qualquer outra Base de Dados) para que possamos explicar passo à passo como fazer desde o carregamento de dados no DataGrid até a edição dos mesmos.

Então devemos criar duas tabelas: Profissionais e Departamentos, onde haverá a relação entre o Profissional e o Departamento qual ele pertence. A seguir a estrutura da tabela para exemplo:



Depois disso devemos criar um novo Projeto no Visual Studio .NET do tipo WebApplication:



Agora devemos arrastar um controle Datagrid da ToolBox para o WebForm. Ao arrastá-lo, remoneie para "dgProfissionais" clicando em suas Propriedades. A idéia é popular esse Datagrid com os dados vindos das tabelas Profissionais e Departamentos da Base de Dados. E além dos campos devemos também criar um Link "Editar" para que quando o usuário clicar, possa editar o registro corrente.

Clique com o botão direito do mouse em cima do DataGrid e em seguida clique em Property Builder. Nessa janela você define a Paginação, Colunas, Estilos, etc. do DataGrid.



Em seguida clique em Columns e desmarque a opção Auto columns automatically at run time, pois com essa opção marcada, o DataGrid criará as colunas em tempo de execução de acordo com a Fonte de Dados informada à ele.



Agora devemos adicionar as colunas que desejamos. Em Avaliable Columns adicione:

  • Button Column Delete (Propriedades: HeaderText: Excluir - Text: X - CommandName: Delete)
  • Template Column (Propriedades: HeaderText: Editar)
  • Bound Column (Propriedades: HeaderText: Nome - Data Field: NomeProfissional)
  • Template Column (Propriedades: HeaderText: Departamento)
  • Template Column (Propriedades: HeaderText: Status)

Explicando as Colunas:

A primeira coluna será apresentada um "X" para que possa excluir o registro. Já a segunda coluna, será colocado um LinkButton para que ao clicar o Usuário possa editar o registro corrente. Na terceira coluna apresentaremos o Nome do Profissional. Na quarta coluna será apresentado o Departamento qual ele pertence. E finalmente a última coluna mostrará o seu Status.

Lembrando que a ordem acima será apresentada quando o DataGrid está apresentando um ItemTemplate ou AlternatingItemTemplate. Quando estamos editando um determinado registro, no lugar do Nome do Profissional, Departamento qual ele pertence e Status, aparecerá um TextBox, DropDownList e CheckBox respectivamente para que o Usuário possa editar conforme a necessidade.

Depois das colunas definidas, devemos agora adicionar o DropDownList e o CheckBox dentro do DataGrid. Para isso, clique com o botão direito do mouse em cima do DataGrid vá até a opção Edit Template e escolha a Coluna [1] "Editar".



O DataGrid ficará disponível para você poder editar as propriedades dos LinkButton"s que lá se encontram. Altere a propriedade Text do LinkButton Delete para Exluir, o Cancel para Cancelar e o Update para Atualizar. Feito isso, clique novamente com o botão direito em cima do DataGrid e selecione a opção: End Template Editing.

Agora devemos repetir o passo acima e fazermos o mesmo para a coluna Departamento. Clique com o botão direito em cima do DataGrid, vá até a opção Edit Template e selecione a Coluna [3] - "Departamento". Quando o DataGrid ficar disponível para editá-lo, adicione à área do ItemTemplate um Label e altere o seu ID para "lblDepartamento", e adicione à área EditItemTemplate um DropDownList e altere o seu ID para "cboDepartamentos". Em seguida clique com o botão direito e selecione a opção End Template Editing.

Entendendo:

Esse processo que acabamos de realizar quer dizer que quando o registro do DataGrid estiver apenas sendo exibido (ItemTemplate) ele aparecerá o Label com o nome do Departamento e quando o registro do DataGrid estiver sendo editado, aparecerá um DropDownList com todos os Departamentos disponíveis.

Para finalizarmos o design ainda falta a coluna Status. Devemos prosseguir da mesma forma que fizermos na coluna Departamentos:



No ItemTemplate colocamos um Label com ID = "lblStatus" para exibir o Status e em EditItemTemplate adicionamos um CheckBox com ID = "chkStatus".

Feito isso, seu DataGrid deverá ficar semelhante à este:



Agora teremos que começar a programar o código de acesso à Base de Dados para que possamos manipular os dados dentro do DataGrid.

No topo da página devemos importar o Namespace SqlClient para que possamos trabalhar com os objetos de acesso à dados do SQL Server:

Imports System.Data.SqlClient

Começaremos à declarar as variáveis que serão utilizadas. No começo da página, após a declaração da classe:

Private m_connectionString As String = "CONNECTION_STRING"
Private m_departamentoSelecionado As String

A variável m_connectionString será utilizada para armazenar a ConnectionString. Uma boa técnica seria armazená-la dentro do arquivo Web.Config.

A variável m_departamentoSelecionado será utilizada para o fixar DropDownList na posição em que o registro se encontra.

Agora devemos criar um rotina para popular o DataGrid, pois precisaremos chamá-la sempre:

Private Sub CarregaGrid()
Dim strSQL As String = "SELECT Profissionais.ProfissionalID, Profissionais.Nome AS NomeProfissional, Profissionais.Status, Departamentos.DepartamentoID, Departamentos.Nome as NomeDepartamento FROM Profissionais INNER JOIN Departamentos ON Profissionais.DepartamentoID = Departamentos.DepartamentoID ORDER BY Profissionais.Nome"
Dim sqlConnection As SqlConnection = New SqlConnection(Me.m_connectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(strSQL, sqlConnection)
Dim sqlDataReader As SqlDataReader

sqlCommand.CommandType = CommandType.Text

Try
sqlConnection.Open()
sqlDataReader = sqlCommand.ExecuteReader()
If sqlDataReader.Read() Then
With Me.dgProfissionais
.DataSource = sqlDataReader
.DataBind()
End With
End If

Catch ex As SqlException
Response.Write("Ocorreu um erro na Base de Dados.")
Catch ex As Exception
Response.Write("Ocorreu um erro inesperado.")
Finally
If Not (sqlDataReader Is Nothing) Then
sqlDataReader.Close()
End If
If sqlConnection.State = ConnectionState.Open Then
sqlConnection.Close()
End If
End Try
End Sub

Depois disso, precisamos executar essa rotina no Evento Load da página:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Page.IsPostBack Then
Call Me.CarregaGrid()
End If
End Sub

Mas neste caso ele irá popular os campos que foram definidos no Property Builder, mas ainda não instruimos ao ASP.NET quais valores colocar nos controles Label que fazem parte das Templates Columns. Devemos mesclar isso com o código HTML.

Abra o arquivo em modo Design e visualize o código HTML. Em ItemTemplate localize a tag e verá que dentro dela haverá o Label chamado "lblDepartamento", logo adicione o seguinte código à propriedade Text:

<asp:Label id=lblDepartamento runat="server" Text="<%# DataBinder.Eval(Container.DataItem, "NomeDepartamento") %>">
</asp:Label>"

Onde "NomeDepartamento" faz parte da Query e atribuímos esse campo ao Label, assim ao carregar o DataGrid já aparecerá o nome do Departamento que o Usuário pertence.

O mesmo deve ser feito para o Label "lblStatus", onde será exibido o Status do Usuário. Para isso localize dentro do código HTML o Label "lblStatus" e atribua à propriedade Text o campo Status retornado da Base de Dados:

<asp:Label id=lblStatus runat="server" Text="<%# DataBinder.Eval(Container.DataItem, "Status") %>">
</asp:Label>"

Temos também que atribuir o Campo Status que é retornado da Base de Dados para a propriedade Checked do CheckBox que está no Template.

<asp:CheckBox id="chkStatus" runat="server" Checked = "<%# DataBinder.Eval(Container.DataItem, "Status") %>">
</asp:Label>"

Agora temos que definir o DataKeyField do DataGrid. Propriedade qual resgatamos o ID do registro que está sendo selecionado. Para isso, podemos definir no próprio código HTML como mostrado abaixo:

<asp:DataGrid id=dgProfissionais runat="server" ... DataKeyField="ProfissionalID">
</asp:DataGrid>

Depois disso, se executarmos a aplicação ela já estará exibindo os dados conforme abaixo:

Funcionalidades

Começaremos a partir de agora darmos funcionalidades dentro do DataGrid tais como: Editar, Excluir, Atualizar e Cancelar.

- Editar

Selecione o Evento EditCommand do DataGrid através dos atalhos do Visual Studio .NET, conforme mostrado na figura abaixo:



Dentro do Evento colocaremos o seguinte código:

Private Sub dgProfissionais_EditCommand(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgProfissionais.EditCommand
Me. dgProfissionais.EditItemIndex = e.Item.ItemIndex
Me.m_departamentoSelecionado = DirectCast(e.Item.FindControl("lblDepartamento"), Label).Text
Call Me.CarregaGrid()
End Sub

Utilizamos a propriedade EditItemIndex para editarmos o registro. Repare que armazenamos na variável "m_departamentoSelecionado" o Nome do Departamento que o Usuário pertence. Depois disso é necessário carregar novamente o DataGrid, e para isso, utilizamos novamente a rotina CarregaGrid(). Vejam o DataGrid em modo de Edição:



Observação Importante: Quando editamos um determinado registro, temos que habilitarmos os controles que estão nas TemplateColumns, que no nosso caso é um DropDownList e um CheckBox. Para isso utilizamos o Evento ItemDataBound do DataGrid. Dentro desse método verificamos se está sendo requerida uma edição de registro. Veremos abaixo como fazer isso para que o usuário possa escolhar a opção desejada:

Private Sub dgProfissionais_ItemDataBound(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgProfissionais.ItemDataBound
If e.Item.ItemType = ListItemType.EditItem Then
Dim strSQL As String = "SELECT Departamentos.DepartamentoID, Departamentos.Nome FROM Departamentos ORDER BY Departamentos.Nome"
Dim sqlConnection As SqlConnection = New SqlConnection(Me.m_connectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(strSQL, sqlConnection)
Dim sqlDataReader As SqlDataReader

sqlCommand.CommandType = CommandType.Text

Try
sqlConnection.Open()
sqlDataReader = sqlCommand.ExecuteReader()

With DirectCast(e.Item.FindControl("cboDepartamentos"), DropDownList)
.DataTextField = "Nome"
.DataValueField = "DepartamentoID"
.DataSource = sqlDataReader
.DataBind()
.SelectedIndex = .Items.IndexOf(.Items.FindByText(Me.m_departamentoSelecionado))
End With

Catch ex As SqlException
Response.Write("Ocorreu um erro na Base de Dados.")
Catch ex As Exception
Response.Write("Ocorreu um erro inesperado.")
Finally
If Not (sqlDataReader Is Nothing) Then
sqlDataReader.Close()
End If
If sqlConnection.State = ConnectionState.Open Then
sqlConnection.Close()
End If
End Try
End If
End Sub

Se a condição for verdadeira, ou seja, o item que está sendo adicionado ao DataGrid deve ser editado, então fazemos um Select na tabela de Departamentos e preenchemos o DropDownList "cboDepartamentos". Depois de preenchido, utilizamos o método FindByText do DropDownList para posicionarmos o mesmo no Departamento qual o Profissional pertence. Reparem que é passado como parâmetro a variável "m_departamentoSelecionado" que está armazenando o nome do Departamento do registro atual.

- Cancelar

Caso o Usuário desista de alterar o registro, devemos deixar habilitado o botão "Cancelar" para que ele possa voltar ao modo normal do DataGrid. Para isso selecione o Evento CancelCommand.



Dentro do Evento colocaremos o seguinte código:

Private Sub dgProfissionais_CancelCommand(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgProfissionais.CancelCommand
Me.dgProfissionais.EditItemIndex = -1
Call Me.CarregaGrid()
End Sub

Quando atribuímos -1 à propriedade EditItemIndex do DataGrid, é porque não desejamos editar nenhum registro. Depois disso, chamamos novamente a rotina "CarregaGrid()" para popular o DataGrid e com isso, cancelamos a edição.

- Excluir

Para podermos excluir através do DataGrid. Da mesma forma que fizemos com o Editar e Cancelar faremos com o Excluir. Devemos selecionar o Evento DeleteCommand.



Dentro do Evento colocaremos o seguinte código:

Private Sub dgProfissionais_DeleteCommand(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgProfissionais.DeleteCommand
Me. dgProfissionais.SelectedIndex = e.Item.ItemIndex
Dim strSQL As String = "DELETE FROM Profissionais WHERE Profissionais.ProfissionalID=" & Convert.ToString(Me.dgProfissionais.DataKeys(e.Item.ItemIndex))
Dim sqlConnection As SqlConnection = New SqlConnection(Me.m_connectionString)
Dim sqlCommand As SqlCommand = New SqlCommand(strSQL, sqlConnection)

sqlCommand.CommandType = CommandType.Text

Try
sqlConnection.Open()
sqlCommand.ExecuteNonQuery()

Catch ex As SqlException
Response.Write("Ocorreu um erro na Base de Dados.")
Catch ex As Exception
Response.Write("Ocorreu um erro inesperado.")
Finally
If sqlConnection.State = ConnectionState.Open Then
sqlConnection.Close()
End If
End Try
Call Me.CarregaGrid()
End Sub

Dentro da variável "strSQL" temos o seguinte parâmetro: Me.dgProfissionais.DataKeys(e.Item.ItemIndex) que na verdade, ele retorna o ID do Profissional do registro corrente de acordo com o DataKeyField que definimos.

- Atualizar

Finalmente chegamos à parte que atualiza os dados do formulário que está dentro do DataGrid na Base de Dados. Para isso utilizamos o método UpdateCommand do DataGrid.



Dentro do Evento colocaremos o seguinte código:

Private Sub dgProfissionais_UpdateCommand(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles dgProfissionais.UpdateCommand
Dim sqlConnection As SqlConnection = New SqlConnection(Me.m_connectionString)
Dim txtProfissional As TextBox = e.Item.Cells(2).Controls(0)
Dim strSQL As String

strSQL = "UPDATE Profissionais SET Nome = @Nome, DepartamentoID = @DepartamentoID, "
strSQL &= "Status = @Status WHERE Profissionais.ProfissionalID = @ProfissionalID"

Dim sqlCommand As SqlCommand = New SqlCommand(strSQL, sqlConnection)

With sqlCommand.Parameters
.Add("@Nome", SqlDbType.VarChar).Value = txtProfissional.Text
.Add("@DepartamentoID", SqlDbType.Int).Value = DirectCast(e.Item.FindControl("cboDepartamentos"), DropDownList).SelectedItem.Value
.Add("@Status", SqlDbType.Bit).Value = DirectCast(e.Item.FindControl("chkStatus"), CheckBox).Checked
.Add("@ProfissionalID", SqlDbType.Int).Value = Convert.ToInt32(Me.dgProfissionais.DataKeys(e.Item.ItemIndex))
End With

sqlCommand.CommandType = CommandType.Text

Try
sqlConnection.Open()
sqlCommand.ExecuteNonQuery()

Catch ex As SqlException
Response.Write("Ocorreu um erro na Base de Dados.")
Catch ex As Exception
Response.Write("Ocorreu um erro inesperado.")
Finally
If sqlConnection.State = ConnectionState.Open Then
sqlConnection.Close()
End If
End Try

Call Me.dgProfissionais.EditItemIndex = -1
Call Me.CarregaGrid()
End Sub

Criamos uma variável do tipo TextBox e atribuimos à ela a TextBox do registro corrente que se encontra na coluna 2 (Célula 2). Criamos uma variável "strSQL" onde montaremos a Query de Update e criamos os SqlParameters que são adicionados ao Command. Executamos e marcamos a propriedade EditItemIndex do DataGrid para -1.

Observação: Sempre utilize SqlParameters, pois com isso o SQL Server consegue fazer Cache da Query, o que a tornará tão performática quanto uma Stored Procedure.

Conclusão: Podemos ver que o DataGrid é um controle que nos fornece grandes funcionalidades. Podemos exibir e editar dados nele, o que torna o processo mais eficiente para o usuário final e de grande facilidade para o desenvolvedor.

Faça o download do código clicando aqui.

Israel Aéce

Israel Aéce - Especialista em tecnologias de desenvolvimento Microsoft, atua como desenvolvedor de aplicações para o mercado financeiro utilizando a plataforma .NET. Como instrutor Microsoft, leciona sobre o desenvolvimento de aplicações .NET. É palestrante em diversos eventos Microsoft no Brasil e autor de diversos artigos que podem ser lidos a partir de seu site http://www.israelaece.com/. Possui as seguintes credenciais: MVP (Connected System Developer), MCP, MCAD, MCTS (Web, Windows, Distributed, ASP.NET 3.5, ADO.NET 3.5, Windows Forms 3.5 e WCF), MCPD (Web, Windows, Enterprise, ASP.NET 3.5 e Windows 3.5) e MCT.