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.
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();
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:
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;
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();
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
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:
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")
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:
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 + "%'";
}
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:
No evento Click do botão de comando
Aplicar Filtro inclua o código abaixo que aplica o filtro usando dois
critérios:
- Cidade que contenha o caractere digitado;
- 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;
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…