开发者

Best way to communicate between forms?

开发者 https://www.devze.com 2023-01-30 17:18 出处:网络
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 wi

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 fun开发者_如何学Pythonctional programming than object oriented programming...

Perhaps I can:

  • Create a static class (or Properties.Settings) for global settings. Cons: every change of data is needed to be copied to the class, I'm looking for something a bit more comfortable and elegant.
  • Use the ugly way of accessing the controls from Application.OpenForms - fixes the problem of passing the main form as parameter. Cons: not very stable.
  • Do something else I haven't thought of. Suggestions? Cons: don't know what it is yet.


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
    }
}


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();
        }
    }
}


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.


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;

0

精彩评论

暂无评论...
验证码 换一张
取 消