17 05 2017
Enviando parâmetros de um formulário para o outro no Windows Forms e WPF
Trocar informações entre formulários é uma necessidade que, sem dúvida, todo programador precisará implementar nas suas aplicações uma hora ou outra. Esse é um aprendizado bem básico, mas que muita gente que está começando fica com dúvida e acaba implementando da pior maneira possível. Pensando nisso, eu resolvi gravar um vídeo bem curto e direto ao ponto, mostrando como enviar parâmetros de um formulário para o outro.
No vídeo eu utilizo um projeto Windows Forms, mas você pode utilizar o mesmo conceito no WPF, caso você não esteja trabalhando com a arquitetura MVVM. Confira o vídeo:
O projeto de exemplo
Nesse vídeo eu utilizei um projeto bem simples, uma vez que o único objetivo era mostrar como podemos fazer a troca de informações entre formulários. No formulário principal (Form1), temos dois TextBoxes e um botão:
A ideia é que, ao clicarmos no botão “Abrir Form2“, nós abriremos o segundo formulário da aplicação. Esse segundo formulário deverá receber o conteúdo que estiver digitado no TextBox “Parâmetro” do primeiro formulário.
No segundo formulário nós temos um TextBox e um botão:
Ao clicarmos no botão “Fechar” do segundo formulário, o conteúdo que estiver digitado no TextBox “Parâmetro” deve ser retornado para o primeiro formulário, mais especificamente no TextBox “Retorno“.
Parâmetros via construtor
A primeira possibilidade que podemos utilizar para enviarmos informações do primeiro formulário para o segundo formulário é através do construtor. Por padrão, os formulários só possuem um construtor padrão que não recebe nenhum parâmetro. Porém, nós podemos criar um segundo construtor no Form2. Esse construtor herdará do construtor principal, porém ele receberá uma string como parâmetro e utilizará o seu valor para preencher o TextBox:
// C# public Form2(string parametro) : this() { textBoxParametro.Text = parametro; }
' VB.NET Public Sub New() InitializeComponent() End Sub Public Sub New(Parametro As String) Me.New() TextBoxParametro.Text = Parametro End Sub
Nota: no C#, não esqueça de herdar do construtor padrão, adicionando a chamada a “this()” na sua assinatura. Já no VB.NET, não esqueça de implementar manualmente o construtor padrão, que fará a chamada ao método “InitializeComponent”, que efetivamente adicionará os controles no formulário.
Com o construtor criado, nós podemos passar o valor do TextBox do primeiro formulário para o segundo formulário:
// C# private void buttonAbrirForm2_Click(object sender, EventArgs e) { using (var form2 = new Form2(textBoxParametro.Text)) { form2.ShowDialog(); } }
' VB.NET Private Sub ButtonAbrirForm2_Click(sender As Object, e As EventArgs) Handles ButtonAbrirForm2.Click Using Form2 As New Form2(TextBoxParametro.Text) Form2.ShowDialog() End Using End Sub
Parâmetros via propriedade
Como pudemos ver acima, nós podemos passar informações do primeiro formulário para o segundo formulário através de parâmetros no construtor. Porém, para passarmos valores de volta do segundo formulário para o formulário principal, não dá para utilizarmos o construtor. Nesse caso, nós temos que criar uma propriedade no Form2 que dará acesso ao texto do TextBox:
// C# public string Parametro { get { return textBoxParametro.Text; } }
' VB.NET Public ReadOnly Property Parametro As String Get Return TextBoxParametro.Text End Get End Property
Feito isso, nós conseguimos acessar o valor de retorno no primeiro formulário:
// C# private void buttonAbrirForm2_Click(object sender, EventArgs e) { using (var form2 = new Form2(textBoxParametro.Text)) { form2.ShowDialog(); textBoxRetorno.Text = form2.Parametro; } }
' VB.NET Private Sub ButtonAbrirForm2_Click(sender As Object, e As EventArgs) Handles ButtonAbrirForm2.Click Using Form2 As New Form2(TextBoxParametro.Text) Form2.ShowDialog() TextBoxRetorno.Text = Form2.Parametro End Using End Sub
E com isso nós temos a troca completa de informações, tanto o envio de informações do Form1 para o Form2 quanto o retorno das informações do Form2 para o Form1.
Uma melhoria extra que podemos fazer nesse exemplo é adicionarmos um “setter” à nossa propriedade. Do jeito que o código está até agora, nós só conseguimos ler o valor da propriedade (ela é readonly). Se implementarmos um “setter” nessa propriedade, nós podemos trabalhar exclusivamente com ela na troca de informações, eliminando a necessidade de criarmos o construtor customizado:
// C# public string Parametro { get { return textBoxParametro.Text; } set { textBoxParametro.Text = value; } }
' VB.NET Public Property Parametro As String Get Return TextBoxParametro.Text End Get Set(value As String) TextBoxParametro.Text = value End Set End Property
Em seguida, na criação do Form2, nós podemos utilizar a propriedade tanto para enviar o parâmetro como para receber o retorno:
// C# private void buttonAbrirForm2_Click(object sender, EventArgs e) { using (var form2 = new Form2()) { form2.Parametro = textBoxParametro.Text; form2.ShowDialog(); textBoxRetorno.Text = form2.Parametro; } }
' VB.NET Private Sub ButtonAbrirForm2_Click(sender As Object, e As EventArgs) Handles ButtonAbrirForm2.Click Using Form2 As New Form2() Form2.Parametro = TextBoxParametro.Text Form2.ShowDialog() TextBoxRetorno.Text = Form2.Parametro End Using End Sub
Não faça isso!
Infelizmente, a pior implementação da trocar informações entre formulários ainda é muito utilizada por aí, que é a alteração do modificador de visibilidade dos controles para “público“. Essa modalidade é muito utilizada porque ela é extremamente fácil de ser implementada. Basta alterar uma propriedade do controle e pronto, teremos acesso irrestrito a todas as suas propriedades:
No vídeo eu mostro um exemplo concreto dos problemas que essa alternativa pode trazer para os nossos projetos. Ao alterarmos o modificador de visibilidade para “público“, nós teremos acesso irrestrito ao controle todo, e não somente à propriedade “Text“. Dessa maneira, nós podemos esconder ou remover o controle do segundo formulário, ou até mesmo alterar completamente o seu comportamento. Obviamente, essa não é uma boa prática, portanto, evite utilizá-la.
Concluindo
No vídeo de hoje você conferiu duas maneiras que podemos utilizar nos nossos projetos Windows Forms e WPF para trocarmos informações entre formulários. A primeira delas é através de parâmetros no construtor. Já a segunda alternativa é utilizarmos propriedades.
Através de parâmetros no construtor nós conseguimos enviar informações em um único sentido (do formulário chamador para o formulário receptor). Por outro lado, ao utilizarmos propriedades, nós conseguimos trocar informações nos dois sentidos.
E você, acredito que já precisou trocar informações entre formulários, não é mesmo? Qual dessas duas alternativas você utilizou? Ou você acabou implementando de alguma outra maneira? Conte-nos mais detalhes na caixa de comentários logo abaixo!
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.
Até a próxima!
André Lima
Photo by Peter Shanks used under Creative Commons
https://pixabay.com/en/startup-start-up-notebooks-creative-593327/
Song Rocket Power Kevin MacLeod (incompetech.com)
Licensed under Creative Commons: By Attribution 3.0 License
http://creativecommons.org/licenses/by/3.0/
Aplicações Android com Xamarin – Parte 1 de N – Prototipando a aplicação Ferramentas de proteção contra pirataria no .NET
Ótimo muito bom mesmo já estou criando um projeto para testar
Muito obrigado, Deuzivaldo! Qualquer dúvida é só entrar em contato..
Abraço!
André Lima
Bom dia !
Primeiro obrigado pela dica, resolveu uma parte do meu problema, eu estou coma seguinte situação, eu tenho um form 1 com um listview e chamo form2 porém eu precisava que ao digitar um valor no textbox do form2 fosse sendo inserido o no listview do form1, poderia me ajudar?
Obrigado
Olá Josiel.
É só seguir a sistemática de envio de valores apresentada no artigo, provavelmente passando o valor desejado via propriedade.. Onde é que você está com dificuldade exatamente?
Abraço.
André Lima
Realmente muito bom exemplos bem construidos
Olá Saulo! Muito obrigado! Fico feliz que você tenha gostado..
Um forte abraço!
André Lima
Olá André! muito bom e útil, Parabéns mais uma vez!
André, imagina o seguinte cenário: Um serviço WCF que será hospedado num servidor WEB (IIS), até este momento eu só consigo mudar a string de conexão do banco de dados através do arquivo Web.config.(muito chato), tem ferramentas capazes de ler o Web.config e fazer alterações? ou é melhor fazer tais coisas no código?
Agradeço pela atenção.
Olá Ademi!
Normalmente as pessoas costumam trabalhar com strings de conexão no arquivo web.config (ou app.config) mesmo, ou em algum outro arquivo de configuração customizado da sua aplicação.. Strings de conexão direto no código é má prática e é algo que você deve evitar a todo custo..
Eu não conheço ferramentas que façam a administração do web.config visualmente.. Eu sempre editei esses arquivos de configuração “na mão”.. Mas, se você pesquisar por “web.config tools”, você encontra algumas opções (eu não testei):
Web Site Administration Tool Overview
XDT (web.config) transform engine
ASP.NET Web Site Administration Tool
Se você encontrar alguma ferramenta interessante, volta aqui e conta pra gente..
Abraço!
André Lima
Ótimo professo. Muito bom mesmo. Obrigado
De nada, Deuzivaldo! Muito obrigado pelo comentário!
Abraço!
André Lima
André, bom dia!
Novamente, excelentes exemplos e esclarecimentos a respeito de comunicação entre Forms.
Se possível, gostaria de uma dica a respeito de como acessar um formulário de uma classe em outro projeto(camada) dentro da mesma solução.
O cenário é o seguinte: Tenho um pequeno aplicativo que decidi construir no padrão MVVM (ou bem próximo disso).
Na classe tenho um SUB “MostraCliente” que recebe como parâmetro o formulário específico. Na hora de manipular os controles dentro da SUB, não são disponibilizados os controles depois do ponto(.). Exemplo: frm. … nome_TextBox e assim por diante.
Já fiz testes para isso de outra maneira, incluindo a classe no mesmo projeto(camada) do formulário e funcionou mas, do jeito que preciso não funcionou.
E também já adicionei referências diversas aos projetos e também não deu certo.
Exemplo da Sub.
————————————————————–
Public Sub MostraCliente (Byval frm as Form_Cadastro_Cliente)
…
…
frm.nome_TextBox.Text = …
End Sub
————————————————————–
Grato pela atenção.
Paulo.
Olá Paulo, muito obrigado pelo comentário!
Imagino que você esteja trabalhando com Windows Forms, correto? Se esse for o caso, aparentemente uma solução seria alterar a visibilidade dos controles (propriedade “Modifiers” nos controles, a partir do designer do formulário).. Como você consegue acessar dentro do mesmo projeto, provavelmente o modificador de visibilidade está definido como “Internal”.. Para conseguir acessar os controles a partir de outro projeto, você precisa alterá-los para “public”..
Caso você queira dispobilizar somente os valores dos controles (sem a possibilidade de alterá-los) seria criar propriedades que só permitem o acesso aos seus valores (propriedades read-only, que teriam somente a parte “Get”)..
Abraço!
André Lima
André, boa tarde!
Agradecido pelas dicas. Vou testar e depois te dou um retorno.
Até+
Paulo.
Beleza, Paulo.. Qualquer coisa estou à disposição..
Abraço!
André Lima
André, boa tarde!
Poderia me dar uma dica de como inserir um item numa ListView, com índice específico, sem perder o item anterior que estava no índice específico? Ou seja, inserir um item remontando a LIstView sem perda dos dados anteriores.
Procurei por métodos no próprio controle e não consegui resolver. Já pensei em algumas rotinas para guardar os dados anteriores e depois atualizar a ListView.
Grato pela atenção.
Paulo.
Olá Paulo!
O ListView é bem flexível e pode ser exibido em diversos tipos de layout.. Às vezes a inserção de itens em uma posição específica acaba não funcionando corretamente.. Como está o layout do seu ListView? Quais propriedades você configurou nele?
Eu começaria dando uma olhada nas sugestões desta thread do StackOverflow:
Inserting an item into a C# Winforms listview
Abraço!
André Lima
André, boa tarde!
Novamente venho solicitar vossos sábios conselhos. Preciso mascarar uma coluna no DataGridView como data (__/__/____) e não consigo encontrar um evento KeyPress na célula específica para que quando o usuário for digitando os dados, eles sejam montados automaticamente naquele formato.
Para os TextBoxs normais existe o evento KeyPress. Já no DGV não encontrei ainda.
Obs: A maioria dos eventos sempre já aconteceu (Changed).
Grato pela atenção!
Paulo.
Olá Paulo!
Você já deu uma olhada neste artigo do CodeProject?
DataGridViewColumn Hosting MaskedTextBox
E aproveita e já dá uma olhada nesta thread do StackOverflow se você tiver problemas com esse controle:
DataGridView Masked TextBox Column
Abraço!
André Lima
Oi André!
Muito grato pelo retorno e dicas. Bem completos os artigos.
Também consegui encontrar um exemplo que faz praticamente a mesma coisa, ou seja, implementa uma MaskedTextBoxColumn no DGV.
Sei que vários amigos já precisaram ou vão precisar resolver esse “probleminha” no seu dia-a-dia de trabalho, por isso segue o link para verificação e estudos:
http://www.vb-tips.com/dbPages.aspx?ID=43d85ac7-1715-47fd-9e1f-dd17b41ace9a
No exemplo citado você deve criar a nova coluna e adicioná-la ao DGV.
Abraço!
Até+
Paulo.
Olá Paulo!
Maravilha, hein! Muito obrigado por compartilhar o link.. Com certeza vai ajudar a quem precisar dessa funcionalidade no futuro..
Abraço!
André Lima