Symbol
Symbol

Reputation: 145

Best way to communicate between forms?

I almost never used (advanced, or at all) graphical interfaces, or one simple form with simple controls... but this time I've got something a little more complex, and I don't have much experience with GUI. I have one main form (and possibly more in the future) from which other sub-forms open (and they might have sub-forms of themselves) and I wonder what is, in your opinion, the best way to communicate between them?

I thought of passing the main form as a parameter to the constructors of the sub-forms, but it doesn't seem like a good way, especially if I'm going to need to communicate between other, distinct, sub-forms, not to mention I have to double check the input, or make a few methods, but it seems more like functional programming than object oriented programming...

Perhaps I can:

Upvotes: 3

Views: 9735

Answers (4)

MatthiasG
MatthiasG

Reputation: 4532

A good way is to declare delegates in the form that want to start the communication. You need a delegate and a callback function:

public delegate void SetValueDelegate(string value);
public SetValueDelegate SetValueCallback;

Another form can then attach to this delegate. At that moment both forms have to know each other, but not after that moment:

firstForm.SetValueCallback += new SetValueDelegate(secondForm.SetValueFunction);

The second form has to declare a function that matches the delegate definition:

public void SetValueFunction(string value)
{
    // do something
}

Now the first form can use the delegate to use the function of the second form (and all other forms or classes that were attached to the delegate:

SetValueCallback(txtParam.Text);

Edit: made an complete example

using System;

namespace DelegateTest
{
    public delegate void SetValueDelegate(string value);

    public class Class1
    {
        public SetValueDelegate SetValueCallBack;

        public void Test()
        {
            if(SetValueCallBack != null)
            {
                SetValueCallBack("Hello World!");
            }
        }
    }

    public class Class2
    {
        public void SetValueFunction(string value)
        {
            Console.WriteLine(value);
        }
    }

    public class Launcher
    {
        public static void Main(string[] args)
        {
            Class1 c1 = new Class1();
            Class2 c2 = new Class2();
            c1.SetValueCallBack += new SetValueDelegate(c2.SetValueFunction);
            c1.Test();
        }
    }
}

Upvotes: 1

LEMUEL  ADANE
LEMUEL ADANE

Reputation: 8818

You can use the built in Tag property of the form which is an "object" class.

public Form1() { (ComplicatedDataStructure)Tag = new ComplicatedDataStracture(); } . . form1 = new Form1(); . . form2 = new Form2(); . . form2.Tag = form1.Tag;

so form2.Tag is equals to "ComplicatedDataStracture" object;

Upvotes: 0

Liviu Mandras
Liviu Mandras

Reputation: 6607

The most flexible, scalable (and IMHO the most professional) way to do it is to use CAB (Composite Application Block). In simple terms CAB is a set of 2-3 assemblies that implement a lot of plumbing required to make complex UI applications the right way and it exposes this plumbing to the user of the library in a nice way. Among others it has a very nice event and command (as in command pattern) system.

The downside: requires some time to learn and not very trivial to grasp.

Here is a comprehensive (but easy to understand) tutorial that will help you make the learning easier.

Upvotes: 0

djdd87
djdd87

Reputation: 68456

Your constructor idea is probably the most sound method of communication back to the main form. Your sub form would do something like the following:

public class SubForm : Form
{
    public SubForm(MainForm parentForm)
    {
        _parentForm = parentForm;
    }

    private MainForm _parentForm;

    private void btn_UpdateClientName_Click(object sender, EventArgs e)
    {
        _parentForm.UpdateClientName(txt_ClientName.Text);
    }
}

And then you expose public methods on your MainForm:

public class MainForm : Form
{
    public void UpdateClientName(string clientName)
    {
        txt_MainClientName.Text = clientName;
    }
}

Alternatively, you can go the other way around and subscribe to events from your SubForms:

public class MainForm : Form
{
    private SubForm1 _subForm1;
    private SubForm2 _subForm2;

    public MainForm()
    {
        _subForm1 = new SubForm1();
        _subForm2 = new SubForm2();

        _subForm1.ClientUpdated += new EventHandler(_subForm1_ClientUpdated);
        _subForm2.ClientUpdated += new EventHandler(_subForm2_ProductUpdated);
    }

    private void _subForm1_ClientUpdated(object sender, EventArgs e)  
    {
        txt_ClientName.Text = _subForm1.ClientName; // Expose a public property
    }

    private void _subForm2_ProductUpdated(object sender, EventArgs e)  
    {
        txt_ProductName.Text = _subForm2.ProductName; // Expose a public property
    }
}

Upvotes: 1

Related Questions