Você está na página 1de 13

iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

José Carlos Macoratti Quinta-feira, 30 de abril de 2009

C# - DataGridView, BindingSource e BindingNavigator


Neste artigo veremos a utilização dos componentes BindingSource, BindingNavigator e DataGridView em aplicações C#.

Sabe porque é importante você conhecer estes componentes?

O componente BindingSource oferece a maneira mais simples e fácil de navegar através de registros em uma fonte de dados; ele foi criado justamente para
simplificar o processo de vinculação com os controles relacionados a uma fonte de dados.

Podemos fazer a vinculação do BindingSource com qualquer um dos seguintes objetos/Interfaces:

ICollection , IList , IListSource, IBindingList e IBindingListViewObject , System.Type , IEnumerable ,

O componente BindingSource veio substituir o componente CurrencyManager e, embora você ainda possa continuar usando o CurrencyManager, o
BindingSource deve ter preferência quando houve a necessidade de vincular os controles de um formulário Windows a uma fonte de dados; dessa forma o
componente BindingSource permite criar um vínculo entre os controles e a fonte de dados. Ele fornece as seguintes vantagens sobre as técnicas de
vinculação anteriores:

Encapsular a funcionalidade do CurrencyManager e expor os eventos do CurrencyManager em tempo de projeto;


Interagir com outros controles windows forms relacionados como por exemplo o BindingNavigator e o DataGridView;

A propriedade DataSource é a propriedade padrão para a classe BindingSource, e o evento padrão é o evento CurrentChanged. Além disso, o BindingSource
fornece métodos, propriedades e eventos como os eventos CurrentItemChanged e DataSourceChanged, que permite uma certa customização.

A propriedade Positon obtém ou define o índice para o item atual na fonte de dados atual, enquanto que o método MoveLast() altera o valor atual da
propriedade Position para o índice do último item na fonte de dados, que é a mesma coisa que obter o valor pela propriedade Count. Ex: Count -1.

O item atual pode ser retornado através da propriedade Current, e a lista inteira pode ser retornada através da propriedade List.

As operações de edição são suportadas no item atual através dos métodos: Current, RemoveCurrent, EndEdit, CancelEdit, Add e AddNew.

1 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Embora o tratamento de valores atualizados seja feito automaticamente para todos os tipos de fonte de dados, a classe fornece os eventos
CurrentItemChanged and DataSourceChanged, que permitem uma customização.

As fontes de dados que são vinculadas ao BindingSource podem ser percorridas e gerenciadas com a classe BindingNavigator, que fornece uma interface para
navegação pelos itens da lista. Embora o BindingNavigator possa ser vinculado a qualquer fonte de dados, ele foi criado para ser integrado com o
BindingSource através da propriedade BindingNavigator.BindingSource

Muitos membros da classe BindingSource operam na lista relacionada representada pela propriedade List, e simplesmente referencia suas operações para lista
relacionada. Desta forma, quando o BindingSource está vinculado a uma implementação customizada de IList, o comportamento dos membros pode diferir
do comportamento descrito na documentação da classe. Assim, o método RemoveAt chama IList.RemoveAt. Na documentação, o método RemoveAt é
descrito considerando que a implementação de IList foi corretamente implementada.

A propriedade padrão para a classe BindingSource é DataSource e o evento padrão é CurrentChanged.

Nota: Como o BindingSource suporta a vinculação a fonte de dados simples e a complexas, a terminologia pode ser confusa. O temo list refere-se à
coleção de dados da fonte de dados, item denota um simples elemento. Para fonte de dados complexas os termos equivalentes table e row são usados.

Exemplos de utilização
//vincular o BindingSource a um componente DataGridView
this.DataGridView1.DataSource = this.clientesBindingSource1;

ou
//obter o número total de items em uma fonte de dados
int count = this.clientesBindingSource.Count;

ou
//obtem ou define um indice para o item atual
int pos = this.clientesBindingSource1.Position;

ou
//move para o último item na lista
this.bindingSource1.Position = this.bindingSource1.Count - 1;

ou
//move para o último item na lista
this.bindingSource1.Position = this.bindingSource1.MoveLast();

2 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Usando BindingSource, BindingNavigator e DataGridView

Veremos agora um exemplo prático usando estes componentes e algumas de suas propriedades e métodos.

Se você deseja navegar através dos registros de uma fontes de dados basta vincular o componente BindingSource a fonte de dados e em seguida vincular os
controles do formulário (TextBox) ao controle BindingSource. Assim, poderemos usar os métodos: MoveNext(), MovePrevious(), MoveFirst(), and
MoveLast() para realizar tal tarefa.

Para o exemplo deste artigo, eu vou usar um banco de dados Microsoft Access que foi criado com o nome Cadastro.mdb e que estará em uma pasta c:\dados
e uma tabela Clientes com a seguinte estrutura:

Abra o Visual C# 2008 Express Edition ou o SharpDevelop 2.2 e crie uma nova aplicação do tipo Windows com o nome DataGridViewBinding.

Neste ponto, se você selecionar no menu Data a opção Add New Data Source e estabelecer uma conexão com o banco de dados Cadastro.mdb, selecionar
um DataSet e escolher a tabela Clientes, você criará um DataSet e, a partir da janela DataSource, poderá selecionar os campos e arrastar para o formulário
criando, assim, de forma automática, toda a interface para navegação pelos registros da tabela e o acesso ao banco de dados conforme pode ser visto na
figura abaixo:

3 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Observe que são criados de forma automática os objetos

TableAdapter, BindingSource e BindingNavigator

além do DataSet.

Mas não é isso que queremos mostrar. Queremos mostrar outra forma de obter o mesmo resultado e aproveitar para mostrar como os componentes
BindingSource e BindingNavigator trabalham em conjunto.

Nosso objetivo será:

Obter os dados da tabela Clientes do banco de dados Cadastro.mdb;


Exibir os dados em um controle DataGridView;

Vamos limpar o projeto e ficar somente com o formulário form1.cs. Agora a partir da ToolBox inclua os seguintes controles no formulário:

Inclua o controle DataGridView no formulário form1.cs a partir da ToolBox e não use assistente que será aberto para selecionar um Data Source;

4 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Vamos agora ao código do formulário clicando na opção View Code.

A primeira coisa que temos que definir é a conexão com o banco de dados, no exemplo estou usando um banco de dados Access, mas poderia usar o SQL
Server.

Vamos incluir então no início do código do formulário a linha de código abaixo para podermos usar as classes para efetuar a conexão com o banco de dados
Cadastro.mdb;
using
System.Data.OleDb;

A seguir no interior da seção:


public
partial class
Form 1 :

Form

Vamos incluir o código a seguir onde estaremos definindo um objeto do tipo BindingSource:
BindingSource bs = new BindingSource();

5 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Iremos atribuir os dados obtidos do banco de dados para o objeto bs e assim o DataGridView e o BindingNavigator podem usá-lo como fonte de dados.

Vamos agora extrair os dados da nossa base de dados.

Vamos usar o evento Load do formulário para efetuar a conexão com o banco de dados usando a seguinte linha de código:
OleDbConnection myConn = new OleDbConnection ("Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:/dados/Cadastro.mdb");

Nota: O provedor para um banco de dados Access pode ser definido assim:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=seu.mdb;Jet OLEDB:Database Password=suasenha;";

Como tratar com banco de dados sempre é uma tarefa sujeita a erros, vamos usar o bloco Try/Catch/Finally para tratar eventuais erros usando o seguinte
código:
private void Form1_Load(object sender, EventArgs e)
{

string conexaoBD = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:/dados/Cadastro.mdb"

OleDbConnection conexao = new OleDbConnection (conexaoBD);

try

//abre a conexão

conexao.Open();

//define o comando sql para selecionar os dados das tabela Clientes

OleDbCommand sql = new OleDbCommand("SELECT * from Clientes", conexao);

//cria um adapter para preencher um dataset

OleDbDataAdapter da = new OleDbDataAdapter(sql);

//define um objeto DataSet

6 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

DataSet ds = new DataSet();

da.Fill(ds);

//atribui o dataset ao DataSource do BindingSource

bs.DataSource = ds;

//atribui o BindingSource ao BindingNavigator

bs.DataMember = ds.Tables[0].TableName;

//Atribui o BindingSource ao DataGridView

dataGridView1.DataSource = bs;

catch (Exception)

MessageBox.Show("erro ao obter os dados.");

finally

conexao.Close();

Executando o projeto iremos obter o seguinte:

7 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Agora vamos usar um recurso do BindingSource para filtrar os dados na exibição do DataGridView. Inclua um controle Combobox no formulário e ativando
o ComboBox Tasks clique no link Edit Items e informe os valores 10, 20, 30 e 40. Inclua uma Label com o texto: Exibir Clientes com idade menor ou igual
a:

Agora no evento SelectedIndexChanged do Combobox inclua o código abaixo onde estamos usando a propriedade Filter do BindingSource.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)

if (comboBox1.Text == "10")

8 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

bs.Filter = "idade <= 10";

if (comboBox1.Text == "20")

bs.Filter = "idade <= 20";

if (comboBox1.Text == "30")

bs.Filter = "idade <= 30";

if (comboBox1.Text == "40")

bs.Filter = "idade <= 40";

A propriedade Filter obtém ou define a expressão usada para filtrar quais linhas serão exibidas.

Geralmente usada em cenários de ligação de dados complexos, a propriedade Filter permite que você exiba um subconjunto da sua fonte de dados. Somente
listas subjacentes que implementam a interface IBindingListView oferece suporte a filtragem.

Quando o filtro não for referência nula, o BindingSource passa essa propriedade para a lista subjacente. Se você definir essa propriedade durante a
inicialização de objeto, a chamada será ser adiada até depois de inicialização for concluída.

Para formar um valor de filtro, especifique o nome de uma coluna seguido por um operador e um valor para filtrar.

O valor da propriedade Filter será mantido quando a fonte de dados for alterada. Para interromper a filtragem da fonte de dados, chame o método
RemoveFilter.

Executando o projeto iremos obter:

9 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Inclua também um botão de comando no formulário e no seu evento Click inclua o código para remover o filtro aplicado usando a propriedade RemoveFilter:
private
void button1_Click(object
sender, EventArgs
e)

bs.RemoveFilter();

Ao clicar no botão o filtro será removido e todos os dados serão exibidos novamente.

Podermos implementar outros filtros, como por exemplo filtrar por nome de forma que ao digitar os caracteres de um nome em uma caixa de texto os dados
serão filtrados e exibidos dinamicamente no DataGridView.

Para implementar este recurso inclua uma Label com o texto: Filtrar por nome e um TextBox - txtNome - no formulário form1.cs e no evento TextChanged
do TextBox inclua o código abaixo que usar a propriedade Filter:
private void
textBox1_TextChanged(object sender,
EventArgs e)

bs.Filter = "Nome like


'%" + txtNome.Text + "%'";

10 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Executando projeto e digitando as letras Ma teremos:

Você pode aplicar um filtro e sobre os dados filtrados aplicar outro filtro obtendo assim como resultado os dados que foram filtrados por critérios distintos em
duas etapas. No exemplo você pode filtrar a idade primeiro e depois filtrar por nome.

Podemos ainda efetuar combinações de condições para criar um filtro com múltiplos critérios sendo aplicados de uma vez. No exemplo acima podemos
definir um critério para filtrar por idade e por cidade.

Vamos então incluir um controle GroupBox e no seu interior dois controles Label: Cidade e Idade e dois TextBox : txtCidade e txtIdade e um Button -
btnFiltrar. Defina o leiaute conforme a figura abaixo:

11 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

No evento Click do botão de comando Aplicar Filtro inclua o código abaixo que aplica o filtro usando dois critérios:

1. Cidade que contenha o caractere digitado;


2. E idade maior que a informada;
private void
btnFiltrar_Click(object sender,
EventArgs e)

{
int id = Convert.ToInt32(txtIdade.Text);
bs.Filter = "cidade like '%" + txtCidade.Text + "%' AND idade > " + id;

Executando o projeto e aplicando o filtro para os dois critérios definidos teremos exibidos os clientes cuja idade for maior que 25 e que a cidade inicie com
San;

12 de 13 5/8/2010 17:11
iMasters - Por uma Internet mais criativa e dinâmica http://imasters.uol.com.br/artigo/12622/csharp/c_datagridview_bindingsource_e_bindingnavigator/im...

Como o foco é mostrar como usar a propriedade Filter do BindingSource eu não estou efetuando validações, o que deve ser feito em uma aplicação de
produção.

Pegue o projeto completo aqui: DataGridViewBinding.zip

Eu sei é apenas C# , mas eu gosto...

13 de 13 5/8/2010 17:11