none
Duvida com Application Form Count RRS feed

  • Pergunta

  •  Boa Tarde, cheguei em uma parte do meu projeto onde preciso fazer uma comunicação entre form Pai e Filho, sem que gere varias janelas.

    Vou passar detalhado meu projeto para entenderem minha necessidade.

    tenho Form1(Pai) Form2(filho)

    Form1 Contem - TabControl e Button1(usado para chamar form2)

    Form2 Contem - Button2(usado para Gerar um button dentro da tabpage do Form1)

    Resumindo ate aqui...

    quando clico no Button1(form1) aparece o form2, quando clico no Button2(form2) aparece outra instancia do Form1 com o button gerado dentro do TabControl.

    Esse processo atende minha necessidade no quesito de gerar o botão, porem tem alguns problemas, pois a cada clique nos botões, novas instancias são criadas, resultando em vários form1 e form2 abertos.

    Como eu quero que o processo funcione.

    clico no Button1(FORM1) > aparece FORM2.

    clico no Button2(FORM2) > retorna para FORM1, cria o button dentro do tabpage, fecha form2.

    clico no Button1(FORM1) > aparece FORM2

    clico no Button2(FORM2) retorna para o Form1 e adiciona outro button no tabpage(agora deveria ter dois botões dentro do tabpage) -- No meu caso atual sempre abre um novo Form(com o botão) nunca o antigo.

    Eu sei que isso esta acontecendo devido as instancias que são criadas aos cliques dos botões. já tentei outras abordagens mas não tive sucesso.

    0 meu Form1(no meu projeto) vai receber muitos dados e estes dados precisam ficar visíveis, portanto não adianta criar uma nova instancia e fechar a anterior, deverá existir apenas uma instancia, pois o projeto é de pedidos e ao clicar no Button1(form2) é gerada a compra e enviada para o banco, é criado um botão no Form1 e ao clicar neste botão criado em tempo de execução mostrara ao lado os dados da compra, entrega e pgto.

    Já fiz alguns teste com MDIParent mas tive problemas com o tabcontrol.

    Gostaria de saber como posso acertar isso

    fazer com que o Form1 seja aberto somente uma vez e que os botões sejam inseridos nele de forma cumulativa,

    quanto ao Form2, não tem problemas instanciar um novo a cada clique.

    OBS: Não estou com problemas para gerar o botão em tempo de execução. O botão é gerado, porem em um novo form1.

    Segue os Codigos:

           ------------------ FORM1--------------------

        public partial class Form1 : Form
        {

            public Form1()
            {
                InitializeComponent();
            }

           public void CriarBotao()
            {
                Button b = new Button();
                Point location = new Point(70, 0);     //Repare que o Método que cria o Botao está dentro do Form1
                b.Name = "Button";                         // Desta maneira eu preciso chamar ele do Form2 e só sei  
                b.Text = b.Name;                            // fazer essa chamada instanciando o Form1.
                location.X = 100;
                location.Y = 10;
                tabPage1.Controls.Add(b);

            }

            private void ChamaForm2(object sender, EventArgs e)
            {

               Form2 frm = new Form2();

               frm.Show()

             } 

        -----------------FORM2--------------------

            private void Button1_Click(object sender, EventArgs e)
            {

               Form1 frm = new Form1();

               frm.CriaControle()

               frm.Show()

             } 

    Att; 


    • Editado Kauec quinta-feira, 10 de agosto de 2017 19:45
    quinta-feira, 10 de agosto de 2017 19:43

Respostas

  • Olha eu aqui :v

    Bom, enquanto ao Form1 está tudo certo, então vamos focar no código do Form2, onde estão os equívocos. Veja o seu código:

    private void Button1_Click(object sender, EventArgs e)
    {
        Form1 frm = new Form1();
        frm.CriaControle();
        frm.Show();
    }

    Todas as linhas sublinhadas estão "erradas" (Pelo menos de acordo com os seus objetivos). Lembra-se do que eu te disse na outra thread? Então, na orientação a objetos, a Classe é só um modelo. Toda vez que você cria uma instancia de uma classe, você cria um novo objeto daquela classe. O maravilhoso disso, é que: Podemos ter várias instancias/objetos de uma mesma classe, mas cada objeto é único, sem ligação com outros objetos/instancias da mesma classe ("sem ligação" em termos de Valores de Propriedades/Atributos, pois desde que são instancias de uma mesma classe, tem as mesmas propriedades e métodos, apenas podem ser diferentes os Valores dessas propriedades).

    Pois bem, esperando que você tenha conseguido compreender isso, vamos ver o que você fez de errado:

    1: Mesmo já tendo uma instancia do Form1, você cria uma nova instancia/objeto, o que vai criar Outro Form, sem relação alguma com o primeiro.

    2: A questão "mágica" a respeito da aparição de outro form, após criar um outro Form, você usa o método Show(), o que faz com que esse novo form, que não tem nada a ver com o primeiro form (Form1), apareça.

    Ok, agora vamos a resolução:

    Você já tem um Form1, o que abre o segundo form (Form2). E você quer fazer uma comunicação entre esses dois, correto? Pois bem, a "palavra-chave" nesse caso é: Referência.

    Mas o que seria? Simples. Como você já conhece um Método, você sabe que você pode chamar métodos passando argumentos. E essa é a solução. Veja bem, desde que você tem que chamar um método, em um determinado objeto, o que você precisa é saber que objeto é esse, certo?

    Nesse caso, você tem o form principal, um objeto do Form1, que abre o segundo. Através do objeto do Form2, você tem que comunicar o objeto do Form1. Então, o que você precisa é: No objeto do Form2, saber que/qual é o objeto do Form1 em que deve-se chamar o método "CriaControle()". E a Referência entra aí. Se o Form1 abre o Form2, a única coisa que deve ser feita é que o Form1 deve dizer ao Form2 (ainda estamos falando de objetos, embora eu fale o nome das classes), que é Ele (O objeto do Form1), em que o Form2 deve chamar o método "CriaControle()".

    Mas como é que faço para o Form2 ter uma referência ao objeto do Form1? Novamente, simples! Lembra-se das variáveis (to zuando não, eu sei que você lembra :v), então. O que você deve fazer é criar uma variável/objeto no Form2 do Form1, para poder armazenar a referência. E então, sempre que precisar, chamar o método através dessa variável/referência/objeto.

    // Criamos a variável que vai armazenar
    // a referência ao objeto do Form1.
    // Note que no tipo da variável,
    // Informamos o "modelo" do objeto,
    // que é a classe do seu Form1.
    private Form1 form1;
    
    public Form2()
    {
        InitializeCOmponent();
    }
    
    // Fazemos uma sobrecarga de construtor,
    // Para quando fizermos a instancia do 
    // Form2 no Form1, podermos passar a
    // Referência ao objeto do Form1
    public Form2(Form1 parent)
    {
        InitializeCOmponent();
        // Assinamos a variável com
        // A referência do objeto do
        // Form1.
        this.form1 = parent;
    }
    
    private void Btn1_CLick(object sender, EventArgs e)
    {
        // Chamamos o método no objeto
        // Do Form1, que é o form que já
        // está aberto.
        form1.CriaControle();
    }

    Nesse "novo" código, o que fazemos é uma sobrecarga no método construtor do Form2. Nele, especificamos que queremos que seja passado um argumento, cujo o Tipo é Form1. Provavelmente você deve estar confuso nessa parte, afinal, você sempre ouviu que quando você passa um argumento pra um método, está passando uma cópia de um determinado valor. Então você se pergunta: "Como é que isso é uma referência? Parece apenas outro objeto, afinal é uma 'cópia'". Bom, isto estaria certo se estivéssemos falando de structs. Porém, os Forms são classes, e são passados como referência. Isto é, não é passado uma cópia de um objeto, é passado o endereço na memória em que aquele objeto está. Portando, o variável "form1" do Form2, tem uma referência ao objeto do Form1. Toda a modificação feita na variável "form1", é refletida no objeto do Form1, pois ambas referem-se ao mesmo espaço na memória; aos mesmos dados. Eu espero que isso não te confunda muito, por isso, leia esse Artigo que fala das diferenças entre Value Types e Reference Types.

    Ok, assumindo que você já entendeu a diferença, agora você sabe que para fazer comunicação entre objetos, um objeto deve ter uma referência ao objeto que deseja comunicar. Isto é, deve saber com quem ele precisa se comunicar. No seu caso, o Form2 agora sabe que ele deve chamar o método "CriaControle()" do objeto do Form1, aquele que já está aberto.

    Resumindo: Não se trata de um outro objeto de Form1 (Como o seu código atual), como é uma referência, estamos falando do objeto que já existe, que é o Form que está aberto e chama o Form2. E a comunicação ocorre perfeitamente :D

    Mais dúvidas é só perguntar.



    • Editado Cliffinho sexta-feira, 11 de agosto de 2017 13:07
    • Marcado como Resposta Kauec sábado, 12 de agosto de 2017 05:46
    sexta-feira, 11 de agosto de 2017 12:58

Todas as Respostas

  • Olha eu aqui :v

    Bom, enquanto ao Form1 está tudo certo, então vamos focar no código do Form2, onde estão os equívocos. Veja o seu código:

    private void Button1_Click(object sender, EventArgs e)
    {
        Form1 frm = new Form1();
        frm.CriaControle();
        frm.Show();
    }

    Todas as linhas sublinhadas estão "erradas" (Pelo menos de acordo com os seus objetivos). Lembra-se do que eu te disse na outra thread? Então, na orientação a objetos, a Classe é só um modelo. Toda vez que você cria uma instancia de uma classe, você cria um novo objeto daquela classe. O maravilhoso disso, é que: Podemos ter várias instancias/objetos de uma mesma classe, mas cada objeto é único, sem ligação com outros objetos/instancias da mesma classe ("sem ligação" em termos de Valores de Propriedades/Atributos, pois desde que são instancias de uma mesma classe, tem as mesmas propriedades e métodos, apenas podem ser diferentes os Valores dessas propriedades).

    Pois bem, esperando que você tenha conseguido compreender isso, vamos ver o que você fez de errado:

    1: Mesmo já tendo uma instancia do Form1, você cria uma nova instancia/objeto, o que vai criar Outro Form, sem relação alguma com o primeiro.

    2: A questão "mágica" a respeito da aparição de outro form, após criar um outro Form, você usa o método Show(), o que faz com que esse novo form, que não tem nada a ver com o primeiro form (Form1), apareça.

    Ok, agora vamos a resolução:

    Você já tem um Form1, o que abre o segundo form (Form2). E você quer fazer uma comunicação entre esses dois, correto? Pois bem, a "palavra-chave" nesse caso é: Referência.

    Mas o que seria? Simples. Como você já conhece um Método, você sabe que você pode chamar métodos passando argumentos. E essa é a solução. Veja bem, desde que você tem que chamar um método, em um determinado objeto, o que você precisa é saber que objeto é esse, certo?

    Nesse caso, você tem o form principal, um objeto do Form1, que abre o segundo. Através do objeto do Form2, você tem que comunicar o objeto do Form1. Então, o que você precisa é: No objeto do Form2, saber que/qual é o objeto do Form1 em que deve-se chamar o método "CriaControle()". E a Referência entra aí. Se o Form1 abre o Form2, a única coisa que deve ser feita é que o Form1 deve dizer ao Form2 (ainda estamos falando de objetos, embora eu fale o nome das classes), que é Ele (O objeto do Form1), em que o Form2 deve chamar o método "CriaControle()".

    Mas como é que faço para o Form2 ter uma referência ao objeto do Form1? Novamente, simples! Lembra-se das variáveis (to zuando não, eu sei que você lembra :v), então. O que você deve fazer é criar uma variável/objeto no Form2 do Form1, para poder armazenar a referência. E então, sempre que precisar, chamar o método através dessa variável/referência/objeto.

    // Criamos a variável que vai armazenar
    // a referência ao objeto do Form1.
    // Note que no tipo da variável,
    // Informamos o "modelo" do objeto,
    // que é a classe do seu Form1.
    private Form1 form1;
    
    public Form2()
    {
        InitializeCOmponent();
    }
    
    // Fazemos uma sobrecarga de construtor,
    // Para quando fizermos a instancia do 
    // Form2 no Form1, podermos passar a
    // Referência ao objeto do Form1
    public Form2(Form1 parent)
    {
        InitializeCOmponent();
        // Assinamos a variável com
        // A referência do objeto do
        // Form1.
        this.form1 = parent;
    }
    
    private void Btn1_CLick(object sender, EventArgs e)
    {
        // Chamamos o método no objeto
        // Do Form1, que é o form que já
        // está aberto.
        form1.CriaControle();
    }

    Nesse "novo" código, o que fazemos é uma sobrecarga no método construtor do Form2. Nele, especificamos que queremos que seja passado um argumento, cujo o Tipo é Form1. Provavelmente você deve estar confuso nessa parte, afinal, você sempre ouviu que quando você passa um argumento pra um método, está passando uma cópia de um determinado valor. Então você se pergunta: "Como é que isso é uma referência? Parece apenas outro objeto, afinal é uma 'cópia'". Bom, isto estaria certo se estivéssemos falando de structs. Porém, os Forms são classes, e são passados como referência. Isto é, não é passado uma cópia de um objeto, é passado o endereço na memória em que aquele objeto está. Portando, o variável "form1" do Form2, tem uma referência ao objeto do Form1. Toda a modificação feita na variável "form1", é refletida no objeto do Form1, pois ambas referem-se ao mesmo espaço na memória; aos mesmos dados. Eu espero que isso não te confunda muito, por isso, leia esse Artigo que fala das diferenças entre Value Types e Reference Types.

    Ok, assumindo que você já entendeu a diferença, agora você sabe que para fazer comunicação entre objetos, um objeto deve ter uma referência ao objeto que deseja comunicar. Isto é, deve saber com quem ele precisa se comunicar. No seu caso, o Form2 agora sabe que ele deve chamar o método "CriaControle()" do objeto do Form1, aquele que já está aberto.

    Resumindo: Não se trata de um outro objeto de Form1 (Como o seu código atual), como é uma referência, estamos falando do objeto que já existe, que é o Form que está aberto e chama o Form2. E a comunicação ocorre perfeitamente :D

    Mais dúvidas é só perguntar.



    • Editado Cliffinho sexta-feira, 11 de agosto de 2017 13:07
    • Marcado como Resposta Kauec sábado, 12 de agosto de 2017 05:46
    sexta-feira, 11 de agosto de 2017 12:58
  • Boa noite, usei este código acima que você me passou, porem estava dando erro na linha

       form1.CriaControle();

    // System.NullReferenceException: 'Referência de objeto não definida para uma instância de um objeto.'

    o meu form1 estava null.

    pesquisei sobre como arrumar isso antes de vir aqui com mais um problema.

    Descobri que precisava passar um argumento referenciando meu form1 no momento da instancia do form2

    Minha chamada para o form2 estava assim  

             Form2 frm = new Form2();

               frm.Show()

    ai acrescentei o THIS e funcionou perfeitamente;

               Form2 frm = new Form2(THIS);

               frm.Show()

    Ajudou demais sua colaboração, obrigado!

    Agora so preciso criar um algoritmo para que os botões sejam inseridos um ao lado do outro.

    valeu!

    sábado, 12 de agosto de 2017 05:46