Click here to Skip to main content
15,916,951 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
I have two forms and i need to get values from one to another:
Example 1:
1. form:
Ce cem = null;
        private void button2_Click(object sender, EventArgs e)
        {       
            if (cem == null || cem.IsDisposed)
            {
                cem = new Ce();
                cem.StartPosition = FormStartPosition.CenterScreen;
                cem.Show();
            }
            else
            {
                cem.BringToFront();
            }
}

on 2. form:
private void button1_Click(object sender, EventArgs e)
        {
            Form1 f1 = (Form1)this.Owner;
            if (radioButton1.Checked == true)
            {
                f1.comboBox4.Text = "First";
            }
            this.Close();
        }

i get the error in line: f1.comboBox4.Text = "First"; it says: Object reference not set to an instance of an object. And i don't get that text from Ce to comboBox4 on Form1.

Example 2: But if i use this:
on 1. form i have:
private void button2_Click(object sender, EventArgs e)
        {
            Ce ce2 = new Ce();
            ce2.Show(this);
        }

and on 2. form i have the code just like above:
private void button1_Click(object sender, EventArgs e)
       {
           Form1 f1 = (Form1)this.Owner;
           if (radioButton1.Checked == true)
           {
               f1.comboBox4.Text = "First";
           }
           this.Close();
       }

in this case works, but for every click on button2 (on Form 1) it will show form Ce again and again. Am i missing something? How to fix example 1 or modify example 2 so it will show only one form?
What is the easiest way to get values from textboxes that are on different forms?
Posted

You are not missing anything. You really show the form of the class Ce over and over. I have no idea why would you do such thing, but you do. Mind you, you do, not anyone else. :-)

Generally, this is the popular question about form collaboration. The most robust solution is implementation of an appropriate interface in form class and passing the interface reference instead of reference to a "whole instance" of a Form. Please see my past solution for more detail: How to copy all the items between listboxes in two forms[^].

Please also see other solutions in this discussion. If the application is simple enough, the solution could be as simple as declaring of some internal property in one form and passing a reference to the instance of one form to the instance of another form. For more complex projects, such violation of strictly encapsulated style and loose coupling could add up the the accidental complexity of the code and invite mistakes, so the well-encapsulated solution would be preferable.

Please see also:
http://en.wikipedia.org/wiki/Accidental_complexity[^],
http://en.wikipedia.org/wiki/Loose_coupling[^].

—SA
 
Share this answer
 
v2
First, I assume you have a good reason for wanting to make your Form, 'cem, have an "Owner."

That you want 'cem to be shown/hidden/closed when the main Form is shown/hidden/closed.

And, that you want 'cem to always appear above the main Form visually. Those two "behaviors" are what the use of the 'Owner property enables: very useful for things like find-and-replace dialogues, and other UI elements you want to be persistent, but, unlike using 'ShowDialog, do not block using the rest of your Application.

In a nutshell: you want an Event ... a Click Event ... of a Button in 'cem to have an effect on a ComboBox in ... what we assume is ... your main Form of Type 'Form1. And, this effect will happen only when a certain RadioButton is "checked."

The road-block you've run into is the fact that: even if you have a valid reference to the Owner of a Form at run-time, you cannot access its private members using that reference.

There are many ways you can go about enabling "communication" between Forms. The general principle (separation of concerns, loose-coupling) that is best to follow is to create the minimum "dependency" between your Application's Objects, to expose to one Object only what it needs to have, or needs to know, to perform specific tasks that require it to have access to some other Object.

Now it is logical, in this case, to claim that there is a hard-coded dependency between your Main Form and the Form 'cem: setting 'cem's 'Owner property creates that behavioral dependency.

On a practical level, what all this means is that we want to be "stingy" with information: we want the Main Form to know only that something happened that requires a change in one of its UI elements; we want the 'cem Form to know "nothing" about "who created it," even though it does have this special relationship with the Main Form via the 'Owner property.

Okay, to bring all this "down to earth," let's get coding:

1. define a private Method with no parameters that does not return a value in the Main Form
C#
private void SetComboBox4()
{
    comboBox4.Text = "First";
}
2. in the 'cem Form definition create a Public property of type 'Action:
public Action TheAction { set; get; }
3. When the Main Form creates an instance of the 'Ce Form, we inject a reference to the 'SetComboBox4 method into the property of type 'Action defined in 'cem:"
C#
public Form1()
{
    InitializeComponent();

    cem = new Ce();
    cem.TopLevel = true;
    cem.StartPosition = FormStartPosition.CenterScreen;
    cem.Owner = this;

    cem.TheAction = SetComboBox4;
}

Ce cem;
4. now, in the Button ClickEventHandler in Form 'cem:
C#
private void button1_Click(object sender, EventArgs e)
{
    if (radioButton1.Checked)
    {
        TheAction();
    }

    this.Hide();
}
We execute the method defined in the Main Form that we have "injected" into 'cem.

If you are new to the concepts of using the 'Action and 'Func forms of Delegates which came into .NET with FrameWork version 3.5 (the first form of Action<T> appeared in .NET 2.0), I encourage you to study: [^], [^], [^].

An investment in learning to use 'Action, and 'Func delegates is well worth your time because: they are very powerful tools used in combination with Linq.

Technically speaking, when we injected the reference to a method into an instance of 'cem: we passed a pointer to the method 'SetComboBox4.

Here's the end result:

Main Form:
using System;
using System.Windows.Forms;

namespace TestTwoForms
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            cem = new Ce();
            cem.TopLevel = true;
            cem.StartPosition = FormStartPosition.CenterScreen;
            cem.Owner = this;

            cem.TheAction = SetComboBox4;
        }

        Ce cem;

        private void button2_Click(object sender, EventArgs e)
        {
            if (! cem.Visible) cem.Visible = true;
        }

        private void SetComboBox4()
        {
            comboBox4.Text = "First";
        }
    }
}
Form 'cem:
C#
using System;
using System.Windows.Forms;

namespace TestTwoForms
{
    public partial class Ce : Form
    {
        public Ce()
        {
            InitializeComponent();
        }

        public Action TheAction { set; get; }

        private void button1_Click(object sender, EventArgs e)
        {
            if (radioButton1.Checked) TheAction();

            this.Hide();
        }
    }
}
 
Share this answer
 
v2
I have figure it out: because i wrote Ce cem = null; i had to change the line from cem.Show(); to cem.Show(this);
1. form:
Ce cem = null;
        private void button2_Click(object sender, EventArgs e)
        {       
            if (cem == null || cem.IsDisposed)
            {
                cem = new Ce();
                cem.StartPosition = FormStartPosition.CenterScreen;
                cem.Show(this);
            }
            else
            {
                cem.BringToFront();
            }
}

Now works like a charm.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900