Click here to Skip to main content
15,915,703 members
Please Sign up or sign in to vote.
1.80/5 (2 votes)
See more:
Hi...
I have three forms(Form1,Form2,Form3).Form1 Contains a function, serial port. Form2 is opened when '1' received from serial port. Form3 is opened in form2's button click. Now I want to access function in form1 from form3. How it can be done without using
Form1 f=new form1();
f.funcname();
Posted
Comments
Prasad Avunoori 17-Sep-14 0:05am    
Make that function as static, so that you can access it as below without creating object.
Form1.funcname();
Sergey Alexandrovich Kryukov 17-Sep-14 0:23am    
Do you understand that it depends on the meaning of form1 and form3; if they are instances, it cannot be static function, which is also a generally bad idea?
—SA
George Jonsson 17-Sep-14 0:51am    
See previous posts in this matter.
Closing form in serialport datareceived event[^]
how to solve error port is closed when calling a function[^]
The old song "Never ending story" comes to mind.
BillWoodruff 17-Sep-14 1:26am    
To help us answer accurately, please answer these questions:

1. is the instance of Form1 the "Main Form," and the instances of Form2, and Form3 are created, and/or displayed (shown), in Form1's code ?

2. is the instance of Form1 the Form that gets a serial-port message ?

3. or, does Form2 display (show) Form3 ?

In other words: which is the Main Form, and where is each Form created ?
Member 10994712 17-Sep-14 1:30am    
code in form1
public void SerialPortValueUpdated()
{
byte[] head = new byte[1] { 0xAA };
byte[] trail = new byte[1] { 0x55 };
byte[] len = new byte[2];


serialPort1.Write(head, 0, 1);
serialPort1.Write(len, 0, 1);
serialPort1.Write(trail, 0, 1);
}

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
int bytes = serialPort1.BytesToRead;

serialPort1.Read(byte_buffer, 0, bytes);

if (byte_buffer[0] == startup&&count==0)
{
if (this.InvokeRequired)
{

this.Invoke(((MethodInvoker)delegate
{

f2 = new Form2();
f2.ShowDialog(this);
// this.Close();
}));
// return;
}


}
}

First, I suggest you study the references Sergey provided to you in his reply, particularly study his example of the use of an Interface to selectively expose fields, properties, or methods of one object/entity/Form/whatever to another.

Also, OriginalGriff has a series of three articles, published in September 2013, on CodeProject, that cover different ways one Form can communicate with another. Here's a link to the first article: [^]. I strongly suggest you study his excellent articles.

I'll show you another way, in this response, to achieve your goal. Using this technique, you'll insert a pointer to a method in the instance of Form1 into the instance of Form3, so the instance of Form3 can use it directly. Note that in this technique the definition of the method in the instance of Form1 can be declared as 'private.

Here's the definition of the method in the code for the instance of Form1 (the Main Form):
C#
public void MethodCalledFromForm3(string s1, string s2)
{
    MessageBox.Show("function called from Form3 result: " + s1 + s2);
}
To make this usable within the instance(s) of Form3 you create we define a template in Form3's code for a method, using .NET's 'Action object [^]:
C#
public Action<string, string> MethodInForm1ToCall;
We have now created a kind of "socket" in Form3 instances into which can be plugged a reference (pointer) to any Method that takes two string arguments, and returns 'void. Technically, an Action is a form of 'Delegate, which you'll learn about as you study the MSDN link; its counterpart that takes a variable number number of arguments and returns a value of some Type, is 'Func.

So, how do we get the method in Form1 whose "signature" matches-up with our "socket" in Form3 "plugged-in" to the instances of Form3 ? It's really easy:
C#
Form3 InstanceOfForm3 = new Form3();

private void Form1_Load(object sender, System.EventArgs e)
{
    InstanceOfForm3.MethodInForm1ToCall = MethodCalledFromForm3;
}
You'll note that I have deliberately not tried to match what you are doing in your code in what's shown here; the reason for this is I hope to make a more generally useful example.

Now, let's put it all together in a "big-picture-view:"
C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private Form2 InstanceOfForm2 = new Form2();
    private Form3 InstanceOfForm3 = new Form3();

    private void Form1_Load(object sender, System.EventArgs e)
    {
        InstanceOfForm2.PropertyInstanceOfForm3 = InstanceOfForm3;

        InstanceOfForm3.MethodInForm1ToCall = MethodCalledFromForm3;
    }

    // show the instance of Form2
    private void button1_Click(object sender, System.EventArgs e)
    {
        InstanceOfForm2.Show();
    }

    // the method to be called in Form3
    private void MethodCalledFromForm3(string s1, string s2)
    {
        MessageBox.Show("function called from Form3 result: " + s1 + s2);
    }
}
In Form2:
C#
public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    // a reference to the instance of Form3 created in Form1
    public Form3 PropertyInstanceOfForm3 { set; get; }

    // show the instance of Form3
    private void button1_Click(object sender, EventArgs e)
    {
        PropertyInstanceOfForm3.Show();
    }
}
In Form3:
C#
public partial class Form3 : Form
{
    public Form3()
    {
        InitializeComponent();
    }

    // the template (delegate) for the method into which a reference (pointer) to the method
   // defined in Form1 will be inserted
    public Action<string, string> MethodInForm1ToCall;

   // call the method in Form1
    private void button1_Click(object sender, EventArgs e)
    {
        MethodInForm1ToCall("I was triggered ", "by clicking the Button in the instance of Form3");
    }
}
In this example Form2 and Form3 instances are created once, in Form1's code. Form1's code injects a reference to the instance of Form3 into Form2, and injects, as explained in detail above, the pointer to the method in Form1 into Form3.

If you can understand what's going on here, you should be able to easily adapt this for your code. In your specific case the 'Action template (delegate) will take no arguments, and you will need to insert the Method on Form1 that matches the Action into Form3 each time you create a new version of it.

Please feel free to ask questions by comments on this answer.
 
Share this answer
 
v3
Comments
Member 10994712 18-Sep-14 6:54am    
@BillWoodruff : If I declare a byte array as static in first form, How can I access it from form3?
As the question turned out to be very popular, and my previous answers often were not well understood, probably were not clear enough, I decided to write a Tips/Trick article complete with detailed code samples and explanations: Many Questions Answered at Once — Collaboration between Windows Forms or WPF Windows.

—SA
 
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