Click here to Skip to main content
15,881,139 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have three forms.
Form1 , Form2 and Form3.
I have a button in form 1.
Form2 and form3 has labels.
When i click on the button in form1.
I want Form2 to show " Hi this is form2" and form3 to show "hi this is form three". on the labels.
Posted
Comments
BillWoodruff 1-Dec-14 19:16pm    
Is this a Windows Forms application, and 'Form1 is the "Main Form" which creates and shows instances of 'Form2 and 'Form3 ?

Please tag your question so we'll know what this is about.
Rewdon 1-Dec-14 19:27pm    
Thanks for the reply.
No it is not the main form.
i have another form called mainForm which is creating all these forms with a help of button.
BillWoodruff 1-Dec-14 19:50pm    
Okay, what-creates-what is important to know !

Note that every time I use the word 'Form here, I refer to a run-time instance of the Type of Form named.

Is it the case that every time you click this Button on Form1, you want the two Labels ... on Form2, Form3 ... to display some content which may be different with each click ? If so, where does that content come from ? Is it generated within Form1, or passed into Form1 from the MainForm ?

I'm going to sketch out one way of achieving multiple secondary Form updates here, but, keep in mind there are many ways you could approach this, and, without really knowing the overall purpose and design of your Application, selecting the best/better way(s) may be just a guess.

A key criterion here for architecture is whether you want to implement a "switchboard" kind of architecture where your Main Form is the "switchboard" and the secondary Forms are analogous to "telephones:" in other words the Main Form is a "hub" where "messages" are received from the secondary Forms, and "messages" are sent to the secondary Forms.

In this model, the secondary Forms do not act on each other directly: they can only trigger actions that are carried out by code in the Main Form.

Another model would be hard-coding messaging between objects/Forms: in this model, Form1 (with the Button) would update the Labels on Form2, and Form3, directly.

The sketch I'll show here is of a "switchboard" type model. It uses Delegates of Type 'Action ('Action and 'Func arrived with .NET Framework 2.0) to pass "messages," rather than using the Event/EventHandler convention. 'Action and 'Func give to C# a powerful syntax for dealing with what in C/C++, or other languages, with passing references to executable code ("function pointers"): 'Action and 'Func can deal with any number of strongly Typed parameters (well, last time I looked, up to seventeen without breaking a sweat).

1. The Main Form:
C#
public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }
    
    private Form1 f1 = new Form1();
    private Form2 f2 = new Form2();
    private Form3 f3 = new Form3();
    
    // just to give each change in the Label content on Form2, Form3
    // a different message ... so you can see if the code is working
    public int count = 0;
    
    private void Form1_Load(object sender, EventArgs e)
    {
        f1.Show();

        // this is where we inject a reference to code in MainForm
        // into the instance of 'Form1
        f1.SendMessage = HandleMessage;
    
        f2.Show();
        f3.Show();
    }
    
    private void HandleMessage(Form form, Control control)
    {
        switch (form.Name)
        {
            case "Form1":
                // got a message from Form1
                switch (control.Name)
                {
                    case "button1":
                        // Button1 on Form1 calling ...
                        // update the Labels on Form2, Form3
                        f2.MsgLabelUpdate("message #" + (++count).ToString());
                        f3.MsgLabelUpdate("message #" + count.ToString());
                        break;
                }
                break;
            // from here on ... just stubbed in to give you ideas
            case "Form2":
                switch (control.Name)
                {
                    case "button1":
                        break;
                    case "label1":
                        break;
                }
                break;
            case "Form3":
                switch (control.Name)
                {
                    case "button1":
                        break;
                    case "label1":
                        break;
                }
                break;
        }
    }
}
Key points to note here are:

a. we injected a reference to executable code ('HandleMessage) into the 'SendMessage Delegate of Type 'Action in the instance of 'Form1.

b. When the Button on Form1 is clicked, it executes the code in the MainForm 'HandleMessage, passing references to the Form, and the Button.

c. When the 'HandleMessage code detects that the message came from Button1 on Form1, it then calls the executable method in Form2, and Form3, which is exposed through their public Delegates of Type 'Action.

d. There's a bunch of other possibilities that are "sketched in" in the 'HandleMessage code just to give you an idea that you could be handling many types of messages from any secondary Form using 'HandleMessage as a general-purpose "transmitter."

2. Form1 ... the Form with the Button ...
C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public Action<Form,Control> SendMessage;

    private void button1_Click(object sender, EventArgs e)
    {
        SendMessage(this, button1);
    }
}
Note, as mentioned, that a reference to the executable code in the Main Form's 'HandleMessage Event was injected into the instance of Form1 by the Main Form.

3. Form2:
C#
public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
        MsgLabelUpdate = invokeLabelUpdate;
    }

    public readonly Action<string> MsgLabelUpdate;

    private void invokeLabelUpdate(string theText)
    {
        label1.Text = theText;
    }
}
Note that here, and in Form3, we don't inject anything into the instance of the Form. We simply create an indirect public reference to the private 'invokeLabelUpdate method that is exposed to Form1

4. Form3:
C#
public partial class Form3 : Form
{
    public Form3()
    {
        InitializeComponent();
        MsgLabelUpdate = invokeLabelUpdate;
    }

    public readonly Action<string> MsgLabelUpdate;

    private void invokeLabelUpdate(string theText)
    {
        label1.Text = theText;
    }
}
Good question to ask:

Is it really necessary to go to all this trouble to create indirect exposure of objects and methods ?

My answer would be that it is not absolutely necessary, but that doing things in this way ... a way which I might call "implementing formal message-passing" ... helps keep our objects (Forms in this case) loosely-coupled, and that is consistent with OO programming ideas that suggest that "separation of concerns" and "encapsulation" is a good thing.

Using the techniques shown here (or others, like them) can ensure that there are minimal possible side-effects resulting from the exposure ... to "outside" objects ... of Forms, Classes, etc.
 
Share this answer
 
v4
Comments
Chris Maunder 1-Dec-14 22:56pm    
gobsmacked.
BillWoodruff 2-Dec-14 1:45am    
I am going to interpret "gobsmacked" as an adjective worth saying 'thanks' for :)

thanks, Bill
Chris Maunder 2-Dec-14 9:31am    
Correct.
Rewdon 2-Dec-14 19:15pm    
hi thanks,
tried the code. built the solution and ran.
one form opens with a button.
when button is clicked nothing happens.
am i missing any references or definitions?
Here's a proof of concept. A better way would be to make a subclass of Form with public method that can be called from the parent form to change the labels.

public partial class Form1 : Form
    {
        private List<Form> children;
        private List<Label> lbls;

        public Form1()
        {
            InitializeComponent();
            this.children = new List<Form>();
            this.lbls = new List<Label>();
            OpenForm(2);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int i = 1;
            foreach (Label l in lbls)
            {
                l.Text = string.Format("This is form{0}", ++i);
            }
        }

        private void OpenForm(int n)
        {
            while (n-- > 0)
            {
                Form f2 = new Form();
                Label l = new Label();
                l.Text = "new form";
                f2.Controls.Add(l);
                f2.Show();
                this.children.Add(f2);
                this.lbls.Add(l);
                f2.Disposed += f2_Disposed;
            }
        }

        void f2_Disposed(object sender, EventArgs e)
        {
            try
            {
                Form f = sender as Form;
                int i = children.IndexOf(f);
                children.RemoveAt(i);
                lbls.RemoveAt(i);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
 
Share this answer
 
Dear,
I think:
in Form child declare delegate event.
C#
public delegate void DelegateFunction(string str);
public event DelegateFunction eDelegateFunction;


and then button click event is
C#
private void btnClick_Click(object sender, EventArgs e)
{
    eDelegateFunction("Text value");
}

In form 1:(form parent)

C#
FormB frm = new FormB();
frm.eDelegateFunction += new FormB.DelegateFunction(frm_eDelegateFunction);
frm.Show();


and declare funtion
C#
private void frm_eDelegateFunction(string strText)
{
    // set text here
    textBox1.Text = strText;
}
 
Share this answer
 
Comments
Rewdon 2-Dec-14 18:46pm    
hi thanks,
according to this code, when the button in first form is clicked new formB is generated.
but i want to show the label with some text in formB which is already open.
cheers
You need to expose the property to Set/Get the Label object of another Form. Consider you have the Label1 in Form2(name=frm2) and Label1 in Form3(name=frm3) respectively which you want to expose(you want to access Label1 of Form2 and Label1 of Form3 from Form1). So expose the property like this.
C#
namespace TestWindowApp
{
    public partial class frm2 : Form
    {
        public frm2()
        {
            InitializeComponent();
        }

        public string LabelText
        {
            get
            {
                return this.label1.Text;
            }
            set
            {
                this.label1.Text = value;
            }
        }
    }
}


Do the same in Form3 also.
Now if Form2 and Form3 is already open and on click of SetLabelButton of Form1 we want to set value to label of Form2 and Form3 respectively, then write down the below code on button click.
C#
private void btnSetLabel_Click(object sender, EventArgs e)
        {
            FormCollection fc = Application.OpenForms;
            foreach (Form item in fc)
            {
                if (item.Name == "frm2")
                {
                    ((frm2)item).LabelText = "This is form2";
                }

                if (item.Name == "frm3")
                {
                    ((frm3)item).LabelText = "This is form3";
                }
            }


        }
 
Share this answer
 
Comments
Rewdon 2-Dec-14 19:14pm    
This worked perfectly fine thank you so much.
Praveen Kumar Upadhyay 2-Dec-14 21:23pm    
My pleasure, and thank you so much for accepting the 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