André Alves de Lima

Talking about Software Development and more…

Trabalhando com data binding no Windows Forms

Eu sei que WPF é a plataforma de desenvolvimento de aplicações desktop mais nova da Microsoft e que o Windows Forms já está aposentado. Entretanto, algumas pessoas podem discordar disso, mas, eu acho que em diversas situações faz mais sentido utilizar o Windows Forms se você já tiver experiência com ele. Porém, o objetivo desse artigo não é fazer uma comparação entre WPF e Windows Forms (eu já escrevi sobre isso uns tempos atrás). O que eu quero realmente mostrar no artigo de hoje é o sistema de data binding no Windows Forms.

Uma vez que é um fato que muitos desenvolvedores ainda trabalham com Windows Forms, é muito importante aprender a trabalhar com essa plataforma da melhor maneira possível. Eu já vi inúmeros desenvolvedores que ficam copiando manualmente dados de controles para classes de dados, ou desenvolvem lógica para ativar ou desativar controles utilizando eventos. Saiba que existe uma maneira muito mais fácil e limpa de implementar esse tipo de funcionalidade. É justamente com a ajuda do data binding que a sua vida vai ficar muito mais tranquila ao desenvolver qualquer tipo de aplicação, seja ela Windows Forms, WPF, Xamarin, UWP, etc.

Quer aprender como funciona o esquema de data binding no Windows Forms? Então vamos lá!

Data binding entre controles

Uma das coisas que podemos implementar com data binding no Windows Forms é a troca de informações entre controles. Nós podemos ligar qualquer propriedade de um controle com qualquer propriedade de outro controle. Por exemplo, imagine que você tenha que habilitar ou desabilitar um botão dependendo do estado de um CheckBox:

Como é que muita gente resolve esse problema? Implementando essa lógica no evento “CheckStateChanged” do CheckBox! Se você implementaria dessa forma, para tudo! Com uma linha de código nós conseguimos fazer uma ligação entre a propriedade “Enabled” do TextBox e a propriedade “Checked” do CheckBox:

            // C#
            btExemplo.DataBindings.Add("Enabled", checkBoxHabilitado, "Checked");
        ' VB.NET
        BtExemplo.DataBindings.Add("Enabled", CheckBoxHabilitado, "Checked")

Veja só o efeito produzido por essa simples linha de código:

Como você pode perceber, data binding entre propriedades de controles é algo muito tranquilo de ser implementado no Windows Forms. Basta acessarmos a propriedade “DataBindings” do controle destino (no nosso caso, o botão) e então chamamos o método “Add” para adicionarmos uma nova ligação (nós podemos ter várias ligações no mesmo controle, utilizando propriedades diferentes).

Os parâmetros para o método “Add” são: a propriedade que receberá o valor no controle destino (no nosso caso, a propriedade “Enabled” do botão), o controle de origem (no nosso caso, o CheckBox) e a propriedade no controle de origem (no nosso caso, a propriedade “Checked” do CheckBox).

Viu só que fácil? Imagine se nós tivéssemos também alguns TextBoxes na tela. Nós poderíamos fazer outros data bindings com a propriedade “Text“, por exemplo:

            // C#
            btExemplo.DataBindings.Add("Text", tbExemplo, "Text");
            tbExemplo.DataBindings.Add("Text", tbExemplo2, "Text");
            tbExemplo2.DataBindings.Add("Text", tbExemplo, "Text");
        ' VB.NET
        BtExemplo.DataBindings.Add("Text", TbExemplo, "Text")
        TbExemplo.DataBindings.Add("Text", TbExemplo2, "Text")
        TbExemplo2.DataBindings.Add("Text", TbExemplo, "Text")

E com essas poucas linhas de código, nós temos esse efeito:

Data binding no DataGridView

Outro exemplo clássico de data binding no Windows Forms é com o controle DataGridView. Nós podemos alimentar o controle de grid com uma coleção de objetos ou com uma DataTable. Para demonstrar essa funcionalidade, vamos adicionar uma nova classe no nosso projeto, dando o nome de “Produto“:

    // C#
    public class Produto
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public decimal ValorUnitario { get; set; }
    }
' VB.NET
Public Class Produto
    Public Property Id As Integer
    Public Property Nome As String
    Public Property ValorUnitario As Decimal
End Class

Em seguida, vamos adicionar as colunas correspondentes no DataGridView:

Atenção! Não esqueça de configurar a propriedade “DataPropertyName” de cada coluna do grid, de modo que elas apontem para a propriedade correspondente da nossa classe:

Feito isso, vamos adicionar uma lista de Produtos no nível do formulário:

        // C#
        private List<Produto> _produtos = new List<Produto>();
' VB.NET
Private Produtos As New List(Of Produto)

Com a lista instanciada, vamos adicionar alguns produtos dentro dela e, em seguida, alimentamos o grid com essa lista através da propriedade “DataSource“:

            // C#
            _produtos.Add(new Produto() { Id = 1, Nome = "Produto 1", ValorUnitario = 1.23m });
            _produtos.Add(new Produto() { Id = 2, Nome = "Produto 2", ValorUnitario = 4.56m });
            _produtos.Add(new Produto() { Id = 3, Nome = "Produto 3", ValorUnitario = 7.89m });

            dgvProdutos.DataSource = _produtos;
        ' VB.NET
        Produtos.Add(New Produto() With {.Id = 1, .Nome = "Produto 1", .ValorUnitario = 1.23})
        Produtos.Add(New Produto() With {.Id = 2, .Nome = "Produto 2", .ValorUnitario = 4.56})
        Produtos.Add(New Produto() With {.Id = 3, .Nome = "Produto 3", .ValorUnitario = 7.89})

        DgvProdutos.DataSource = Produtos

Ao executarmos a aplicação, aparentemente tudo funcionou corretamente:

Mas, será que tudo está funcionando mesmo? O que será que aconteceria se nós adicionássemos um novo produto na lista em tempo de execução? Vamos testar?

Para checarmos esse cenário, vamos implementar uma lógica para o evento “Click” do nosso botão. Quando o botão for clicado, nós vamos alterar o texto do primeiro produto da lista utilizando o conteúdo digitado no TextBox e, além disso, nós adicionaremos um novo produto utilizando um ID sequencial:

        // C#
        private int _ultimoId = 3;
        private void btExemplo_Click(object sender, EventArgs e)
        {
            _produtos[0].Nome = tbExemplo.Text;
            _produtos.Add(new Produto() { Id = ++_ultimoId, Nome = _ultimoId.ToString(), ValorUnitario = _ultimoId });
        }
    ' VB.NET
    Private UltimoId = 3
    Private Sub BtExemplo_Click(sender As Object, e As EventArgs) Handles BtExemplo.Click
        Produtos(0).Nome = TbExemplo.Text
        UltimoId += 1
        Produtos.Add(New Produto() With {.Id = UltimoId, .Nome = UltimoId.ToString(), .ValorUnitario = UltimoId})
    End Sub

Se testarmos essa implementação, veremos que o novo produto não será exibido no grid e, além disso, temos um comportamento bem estranho quanto à alteração do texto no primeiro produto. O grid só entende que ele foi modificado depois de navegarmos para outra linha:

Por que tivemos esse efeito? E como é que podemos resolve-lo?

A classe BindingList

O primeiro problema na nossa implementação é o fato de termos utilizado a classe “List” para criarmos a nossa coleção de produtos. A classe “List” não foi desenvolvida com o intuito de ser utilizada em data binding. Porém, não se preocupe. Para isso nós temos a classe “BindingList“, que é justamente uma “List” que suporta data binding!

Se trocarmos a declaração da nossa coleção de produtos por uma BindingList, nós teremos um resultado um pouco melhor:

        // C#
        private System.ComponentModel.BindingList<Produto> _produtos = new System.ComponentModel.BindingList<Produto>();
' VB.NET
Private Produtos As New System.ComponentModel.BindingList(Of Produto)

Veja que o texto do primeiro produto foi alterado de imediato. Além disso, o novo produto que inserimos na lista em tempo de execução também foi exibido com sucesso. Porém, nós ainda temos um probleminha a ser resolvido. Se nós continuarmos inserindo novas linhas no grid, chega uma hora em que o grid para de atualizar o nome do primeiro produto:

Isso acontece porque a nossa classe “Produto” não implementa a interface “INofifyPropertyChanged“.

A interface INotifyPropertyChanged

A interface INotifyPropertyChanged é utilizada para que o mecanismo de data binding seja notificado quando o valor de uma propriedade for alterado. Nas classes internas do .NET (nos controles do Windows Forms, por exemplo), isso tudo já está implementado nativamente. Porém, se criarmos novas classes no nosso projeto (como foi o caso da classe “Produto” que criamos nesse exemplo), nós temos que implementar essa interface caso a classe venha a ser utilizada em algum data binding.

Essa não é uma particularidade do Windows Forms. Muito pelo contrário, essa interface é essencial também no famoso data binding do WPF. Se não implementarmos essa interface nas nossas classes, nós teremos esse mesmo problema no WPF.

Uns tempos atrás eu escrevi um artigo falando das interfaces de notificação de alteração no WPF. Hoje eu só vou mostrar como implementá-las nesse exemplo, e não vou entrar em muitos detalhes sobre elas. Caso você queira aprender mais sobre esse assunto, confira o artigo que eu acabei de mencionar.

A implementação da interface INotifyPropertyChanged é muito tranquila. Nós só temos que disparar o evento “NotifyPropertyChanged” em todos os “setters” das nossas propriedades (que agora não poderão ser auto-implementadas):

    // C#
    public class Produto : System.ComponentModel.INotifyPropertyChanged
    {
        private int _id;
        public int Id
        {
            get { return _id; }
            set 
            { 
                _id = value;
                OnPropertyChanged("Id");
            }
        }
        private string _nome;
        public string Nome
        {
            get { return _nome; }
            set 
            { 
                _nome = value;
                OnPropertyChanged("Nome");
            }
        }
        private decimal _valorUnitario;
        public decimal ValorUnitario
        {
            get { return _valorUnitario; }
            set 
            { 
                _valorUnitario = value;
                OnPropertyChanged("ValorUnitario");
            }
        }
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }
' VB.NET
Public Class Produto
    Implements System.ComponentModel.INotifyPropertyChanged

    Private _id As Integer
    Public Property Id As Integer
        Get
            Return _id
        End Get
        Set(value As Integer)
            _id = value
            OnPropertyChanged("Id")
        End Set
    End Property

    Private _nome As String
    Public Property Nome As String
        Get
            Return _nome
        End Get
        Set(value As String)
            _nome = value
            OnPropertyChanged("Nome")
        End Set
    End Property

    Private _valorUnitario As Decimal
    Public Property ValorUnitario As Decimal
        Get
            Return _valorUnitario
        End Get
        Set(value As Decimal)
            _valorUnitario = value
            OnPropertyChanged("ValorUnitario")
        End Set
    End Property

    Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    Private Sub OnPropertyChanged(ByVal PropertyName As String)
        RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
    End Sub
End Class

Se testarmos o comportamento do grid mais uma vez depois dessa alteração, nós veremos que agora ele se comportará corretamente:

Como você deve ter notado, a implementação da interface INotifyPropertyChanged pode acabar sendo um pouco “maçante“. Imagine termos que implementar todo esse código em todas as nossas classes de modelo? Vai dar um certo trabalho. É pensando nisso que a Microsoft vem investindo em novas funcionalidades no C# e VB.NET para facilitar a nossa vida. Eu já escrevi uns tempos atrás sobre o atributo CallerMemberName, que facilita um pouco esse processo. Se pesquisarmos na internet, encontraremos maneiras mais fáceis de implementarmos essa interface, como esta que eu encontrei no StackOverflow:

    // C#
    public class Produto : System.ComponentModel.INotifyPropertyChanged
    {
        private int _id;
        public int Id
        {
            get { return _id; }
            set { SetField(ref _id, value); }
        }
        private string _nome;
        public string Nome
        {
            get { return _nome; }
            set { SetField(ref _nome, value); }
        }
        private decimal _valorUnitario;
        public decimal ValorUnitario
        {
            get { return _valorUnitario; }
            set { SetField(ref _valorUnitario, value); }
        }

        protected bool SetField<T>(ref T field, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value))
                return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }
' VB.NET
Public Class Produto
    Implements System.ComponentModel.INotifyPropertyChanged

    Private _id As Integer
    Public Property Id As Integer
        Get
            Return _id
        End Get
        Set(value As Integer)
            SetField(_id, value)
        End Set
    End Property

    Private _nome As String
    Public Property Nome As String
        Get
            Return _nome
        End Get
        Set(value As String)
            SetField(_nome, value)
        End Set
    End Property

    Private _valorUnitario As Decimal
    Public Property ValorUnitario As Decimal
        Get
            Return _valorUnitario
        End Get
        Set(value As Decimal)
            SetField(_valorUnitario, value)
        End Set
    End Property

    Protected Function SetField(Of T)(ByRef field As T, value As T, <System.Runtime.CompilerServices.CallerMemberName> Optional propertyName As String = Nothing) As Boolean
        If EqualityComparer(Of T).[Default].Equals(field, value) Then
            Return False
        End If
        field = value
        OnPropertyChanged(propertyName)
        Return True
    End Function

    Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
    Private Sub OnPropertyChanged(ByVal PropertyName As String)
        RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
    End Sub
End Class

Sincronia entre DataGridView e outros controles

Algo muito mágico que nós recebemos “de brinde” ao utilizarmos data binding no Windows Forms é ligação entre o registro selecionado no grid e outros controles que estejam ligados com a mesma coleção. Para entendermos como isso funciona, vamos adicionar três TextBoxes na nossa janela. Cada TextBox representará uma propriedade da nossa classe “Produto“:

Se adicionarmos um data binding em cada um dos TextBoxes, ligando a propriedade “Text” deles com a propriedade correspondente da coleção de produtos, veja só a “mágica” que acontece automaticamente:

            // C#
            tbId.DataBindings.Add("Text", _produtos, "Id");
            tbNome.DataBindings.Add("Text", _produtos, "Nome");
            tbValorUnitario.DataBindings.Add("Text", _produtos, "ValorUnitario");
        ' VB.NET
        TbId.DataBindings.Add("Text", Produtos, "Id")
        TbNome.DataBindings.Add("Text", Produtos, "Nome")
        TbValorUnitario.DataBindings.Add("Text", Produtos, "ValorUnitario")

Com DataSet e DataTable você não precisa de INotifyPropertyChanged

Como mencionei anteriormente, os controles do Windows Forms já implementam a interface INotifyPropertyChanged nativamente. Isso também acontece com diversas outras classes do .NET Framework, como, por exemplo, DataSet e DataTable. Para verificarmos se isso é realmente verdadeiro, vamos adicionar uma DataTable no nosso formulário:

    // C#
    private DataTable _produtosDT = new DataTable();
' VB.NET
Private ProdutosDT As New DataTable()

Em seguida, vamos substituir a nossa implementação, de forma que os data bindings considerem a DataTable (e não a coleção de produtos):

            // C#
            _produtosDT.Columns.Add("Id", typeof(int));
            _produtosDT.Columns.Add("Nome");
            _produtosDT.Columns.Add("ValorUnitario", typeof(decimal));

            _produtosDT.Rows.Add(1, "Produto 1", 1.23m);
            _produtosDT.Rows.Add(2, "Produto 2", 4.56m);
            _produtosDT.Rows.Add(3, "Produto 3", 7.89m);

            dgvProdutos.DataSource = _produtosDT;

            tbId.DataBindings.Add("Text", _produtosDT, "Id");
            tbNome.DataBindings.Add("Text", _produtosDT, "Nome");
            tbValorUnitario.DataBindings.Add("Text", _produtosDT, "ValorUnitario");
        ' VB.NET
        ProdutosDT.Columns.Add("Id", GetType(Integer))
        ProdutosDT.Columns.Add("Nome")
        ProdutosDT.Columns.Add("ValorUnitario", GetType(Decimal))

        ProdutosDT.Rows.Add(1, "Produto 1", 1.23)
        ProdutosDT.Rows.Add(2, "Produto 2", 4.56)
        ProdutosDT.Rows.Add(3, "Produto 3", 7.89)

        DgvProdutos.DataSource = ProdutosDT

        TbId.DataBindings.Add("Text", ProdutosDT, "Id")
        TbNome.DataBindings.Add("Text", ProdutosDT, "Nome")
        TbValorUnitario.DataBindings.Add("Text", ProdutosDT, "ValorUnitario")

Não esqueça também de alterar o código do clique do botão!

        // C#
        private void btExemplo_Click(object sender, EventArgs e)
        {
            _produtosDT.Rows[0]["Nome"] = tbExemplo.Text;
            _produtosDT.Rows.Add(++_ultimoId, _ultimoId.ToString(), _ultimoId);
        }
    ' VB.NET
    Private Sub BtExemplo_Click(sender As Object, e As EventArgs) Handles BtExemplo.Click
        ProdutosDT.Rows(0)("Nome") = TbExemplo.Text
        UltimoId += 1
        ProdutosDT.Rows.Add(UltimoId, UltimoId.ToString(), UltimoId)
    End Sub

Execute a aplicação e observe que o efeito será exatamente o mesmo que tivemos com a nossa coleção de produtos.

Baixe o projeto de exemplo

Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.

Concluindo

O data binding no Windows Forms é um conceito que eu infelizmente vejo pouquíssimas pessoas utilizando. Eu verdadeiramente espero que os desenvolvedores optem por não utilizar data binding simplesmente por falta de conhecimento. Como você pode perceber, tem muita coisa que pode ser resolvida com pouquíssimas linhas de código utilizando data binding que levariam dezenas e dezenas de linhas sem a sua utilização.

Você já conhecia tudo isso que eu apresentei aqui nesse artigo? Se sim, conte mais sobre as suas experiências nos comentários. E se você não tinha conhecimento sobre o funcionamento do data binding no Windows Forms, agora não tem mais desculpa. Pare de ficar implementando código manual para copiar informações de controles em classes de dados, utilize data binding e o seu código ficará muito mais limpo!

Até a próxima!

André Lima

Image by Pixabay used under Creative Commons
https://pixabay.com/en/chain-metal-chain-link-257490/

Newsletter do André Lima

* indicates required



Powered by MailChimp

33 thoughts on “Trabalhando com data binding no Windows Forms

  • deuzivaldo disse:

    Professor isso foi muito bom mesmo eu estava precisando em um projeto
    Muito obrigado valeu mesmo

  • Ronaldo disse:

    Muito bom o artigo!!

    Só uma coisa, seguindo sua explicação e colocando o código abaixo no evento “CheckStateChanged” no controle checkBox

    // C#
    btExemplo.DataBindings.Add(“Enabled”, checkBoxHabilitado, “Checked”);

    Ocorre o erro “ArgumentException” ao rodar e clicar no checkbox para várias vezes.

    Motivo:
    “Every Control can have only one binding at a time. It looks like you already have a binding to the textboxes before and now when you try to rebind it, it throws an error. You need to clear the old binding before adding a new one.”

    Então para evitar isso tem que colocar antes dessa linha o seguinte:

    btExemplo.DataBindings.Clear();

    Fonte: https://stackoverflow.com/questions/23236318/this-causes-two-bindings-in-the-collection-to-bind-to-the-same-property-paramet

    • andrealveslima disse:

      Olá Ronaldo, obrigado pelo comentário!

      Mas você não precisa colocar esse código no CheckStateChanged.. Essa é justamente a maneira “errada” de se trabalhar.. Como falei no artigo:

      … Como é que muita gente resolve esse problema? Implementando essa lógica no evento “CheckStateChanged” do CheckBox! Se você implementaria dessa forma, para tudo! Com uma linha de código nós conseguimos fazer uma ligação entre a propriedade “Enabled” do TextBox e a propriedade “Checked” do CheckBox…

      Essa linha de código você coloca na inicialização do formulário (por exemplo, no construtor depois do InitializeComponents ou no evento Load do formulário).. Você não precisa lidar com o evento CheckStateChanged.. Sacou?

      Abraço!
      André Lima

  • Arthur Jardim disse:

    Muito legal, excelente post Andre =)

  • Bom dia André!

    Agradeço por mais este excelente post.

    Abraço

  • Aristóteles Junior disse:

    _produtos.Add(new Produto() { Id = ++_ultimoId, Nome = _ultimoId.ToString(), ValorUnitario = _ultimoId });
    }

    Desculpem a minha ignorância, mas neste trecho de código acima, onde encontro a declaração deste “_ultimoId” ? E onde encontro o link para baixar o projeto?

    • andrealveslima disse:

      Olá Aristóteles!

      Esse “_ultimoID” é somente uma variável de controle no nível do formulário que guarda qual foi o último ID utilizado.. Note a declaração iniciando com valor “3” na linha acima do método “btExemplo_Click”..

      Quanto ao projeto de exemplo, vou mandar o link no seu e-mail..

      Abraço!
      André Lima

  • deuzivaldo disse:

    Bom dia professor gostei do post
    Mais tenho uma pergunta, eu tenho uma tela de login com uma checkbox,quando o usuário marca ela,ela salva a senha gostaria de saber se tem como usar esta fusão nela do Data binding.

    • andrealveslima disse:

      Olá Deuzivaldo, obrigado pelo comentário!

      Nesse cenário, data binding não se encaixa muito bem.. Ele serve mais para quando queremos ligar propriedades de um controle com propriedades de outro controle (ou propriedades de um outro objeto).. No seu caso, pelo que eu entendi, ao marcar o checkbox, você quer executar uma lógica que não tem nada a ver com a interface do usuário (que é salvar a senha digitada).. Dessa forma, não vejo como o data binding te ajudaria nessa situação.. O jeito, na minha opinião, é implementar a lógica no evento mesmo..

      Abraço!
      André Lima

  • Marcelo disse:

    Muito obrigado, ótimo artigo!

    Uma dúvida, seguindo o seu exemplo se eu quiser desabilitar (Enabled = false) um botão caso um checkBox esteja marcado (true) como seria?
    Tentei fazer isso e não consegui.

    Desde já agradeço.

    • andrealveslima disse:

      Olá Marcelo, obrigado pelo comentário!

      Nesse caso, você precisa criar um converter para fazer a inversão do valor booleano a ser utilizado no binding.. O converter no Windows Forms nada mais é que um ConvertEventHandler.. Você pode colocar um método como este em algum lugar “comum” do seu projeto:

              public static void InvertBooleanConverter(object sender, ConvertEventArgs e)
              {
                  if (e.Value is bool)
                      e.Value = !(bool) e.Value;
              }
      

      Aí você altera o seu binding para utilizar esse converter com os eventos Format e Parse (além do último parâmetro adicional na criação do binding que deve ter o valor “true”):

      var binding = btExemplo.DataBindings.Add("Enabled", checkBoxHabilitado, "Checked", true);
      binding.Format += InvertBooleanConverter;
      binding.Parse += InvertBooleanConverter;
      binding.ReadValue();
      

      Pronto! Dessa forma o binding vai considerar o valor invertido da propriedade.. Ou seja, quando o CheckBox estiver marcado, o botão estará desabilitado, e vice-versa..

      Abraço!
      André Lima

  • João Victor disse:

    Texto claro e explicativo. É assim que a gente percebe que não sabe nada rsrs

    • andrealveslima disse:

      Muito obrigado, João Victor! Respondi o seu e-mail com as questões que você fez sobre o e-book.. Dá uma olhada lá depois e me avisa se ficou claro..

      Um forte abraço!
      André Lima

  • André Lucas Silva Freires disse:

    Obrigado pela postagem, conteúdo legal.

  • Paulo Leal disse:

    Excelente postagem André, texto claro o objetivo.

    tenho uma dúvida, é possível executar o DataBindings associado a uma propriedade de um objeto que eu criei, por exemplo status de uma conexão (True, False)?

    Escrevi o código abaixo, mas ele só atualiza no inicio da aplicação, se durante a aplicação o valor da conexão mudar o botão não fica inativo, coloquei o código após o InitializeComponent.

    bntExemplo.DataBindings.Add(“Enabled”,meuobjeto , “Conexao”);

    Conexao é uma propriedade booleana do meu objeto.

    • andrealveslima disse:

      Olá Paulo, muito obrigado pelo comentário!

      Você pode, sim, configurar data bindings com propriedades dos seus objetos.. Porém, essa propriedade deverá ser uma propriedade “full” (ou seja, que tenha um atributo por trás dela, e que os getters e setters trabalhem com base no valor desse atributo).. Além disso, você precisará implementar o padrão INotifyPropertyChanged nessa sua classe de conexão e utilizar o padrão dessa interface para notificar quando o valor dessa propriedade alterar..

      Eu expliquei isso na seção “A interface INotifyPropertyChanged” aqui no artigo.. Dá mais uma olhada e veja se você entende o funcionamento.. Se ficar com alguma dúvida, é só escrever outro comentário que eu te ajudo de outra maneira..

      Abraço!
      André Lima

  • Denis disse:

    É possivel implementar o CallerMemberName no .net 4.0 ?

  • Rafael disse:

    Bom dia Professor!

    Estou com um dilema, tem um tempinho, até acho ser bem fácil o que vou pedir, mas nao sei para onde direcionar. Seguinte, tenho um sisteminha ligado a um dataset tipado e tem algumas telas que vai ter o cabeçalho(alguns textBox) e filhos(gridviews), só que se eu vincular na gridview algum datatable, ela vai trazer todos os dados e não só daquele registro que esta mostrando no cabeçalho, queria saber como faço para vincular meu cabeçalho com meus filhos(gridviews), que a medida que for movimentando meus registros pelo bindingnavigation, possa aparecer nos gridviews somente os registros referentes ao cabeçalho.

    Obrigado

    • andrealveslima disse:

      Olá Rafael!

      Pelo que eu entendi, você está querendo montar um mestre/detalhe com dois grids, correto? Se esse for o caso, você já tentou dar uma olhada neste exemplo:

      Creating a Master/Detail Form Using Two Windows Forms DataGridView Controls

      Abraço!
      André Lima

      • Rafael disse:

        Boa tarde Professor!

        Criei um dataset tipado que criou um arquivo .XSD com todo o meu banco de dados, ou seja, tenho ele todo tipado. Quando vou vincular ou um textbox, ou um BindingNavigation ou uma GridView, já puxo direto dessa dataset pronta. Tenho a seguinte questão:

        Tenho uma tela com uma BindingNavigation, tres textBox fazendo o papel do registro mestre e uma gridview fazendo o papel dos registros filhos desse registro mestre. Queria saber como faço pra vincular pela chave esse registro mestre com a tabela dos registros filhos para que venha somente o que for igual ao codigo do registro mestre. Pq toda vez que eu vinculo a gridview com uma tabela da DATASET do arquivo .XSD ele traz todos os dados, mesmo nao sendo do registro mestre que esta mostrando a tela. Quero que quando mexo no BindingNavigation mude o registro mestre e traga os registros filhos referentes a este. Entendi a explicação do que vc me passou, porem ele nao usa um dataset tipado, ele cria o dataset em tempo de execucao

        Obrigado e desculpa a pergunta infantil

        • andrealveslima disse:

          Olá Rafael!

          A ideia é exatamente a mesma.. Desde que você tenha os relacionamentos entre as tabelas no seu DataSet tipado, você só precisa setar o DataSource do grid apontando para o BindingSource que você está utilizando para os campos “mestre”.. Aí, você seta o DataMember do grid com o nome do relacionamento entre as tabelas mestre e detalhe.. Dessa forma os dados serão filtrados automaticamente dependendo do registro selecionado no navigator..

          Por exemplo, digamos que você tenha uma tabela chamada “Mestre” e outra chamada “Detalhe”.. E que o relacionamento entre essas duas tabelas no DataSet se chama “Mestre_Detalhe”.. Você só precisa setar o DataSource do grid da seguinte maneira:

                      dataGridView1.DataSource = mestreBindingSource; // mestreBindingSource é o BindingSource utilizado pelos campos "mestre" do seu formulário
                      dataGridView1.DataMember = "Mestre_Detalhe"; // "Mestre_Detalhe" é o nome do relacionamento entre as tabelas "Mestre" e "Detalhe"
          

          Abraço!
          André Lima

  • MANOEL ÉRIK PEREIRA DA SILVA disse:

    Estou tentando passar um registro de uma linha de DataGridView para TextBoxcom o seguinte c´dooigo : “Cliente cliente = dgvPesquisar.SelectedRows[0].DataBoundItem as Cliente;” . Cliente é uma classe com os elemetos do registro (id, Nome, etc.) e dgvPesquisar é o DataGridView. Mas o Cliente fica nulo (Mensagem:System.NullReferenceException: ‘Referência de objeto não definida para uma instância de um objeto.) Se usar DataBinding daria certo? Observação: usei o mesmo código (tudo igual apenas mudando o BD e a tabela) e o erro não aparece.

    • andrealveslima disse:

      Olá Manoel!

      Depende de como você está alimentando o grid.. Você está realmente alimentando com uma lista de Clientes? Ou você está alimentando com uma DataTable contendo as informações dos clientes? Você só conseguirá fazer o cast caso você esteja realmente alimentando o grid com uma lista de clientes..

      Mas, de qualquer forma, com Data Binding ficaria mais fácil.. Tente seguir as instruções apresentadas no artigo e veja se dá certo no seu cenário..

      Abraço!
      André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *