How to open a new form in c. Adding forms. Interaction between forms. Call a parent form method from a child form

The question addressed in this article is more likely to relate to the topic of building an application architecture, and not specifically to the problem under consideration. Transferring data from one form to another is not difficult at all. To do this, it is enough to make the control whose data we want to obtain open, that is, mark it with the public modifier. Also, another option is possible. For example, in the first form we create an object of the second form by passing a reference to ourselves to the constructor, that is, by passing a reference to the first from the first form to the second
SecondForm secondForm = new SecondForm(this);
Naturally, before doing this, you should take care of creating an overload for the constructor of the second form.

And this method is quite common. However, with its simplicity, it carries many potential problems, the main one being a violation of the principle of encapsulation. In a word, the second form should not know anything about the existence of the first and, even more so, should not be able to influence it.

The solution to this problem is quite simple. Let's look directly at the code. In the designer, we create the main form (it will be launched when the application starts). Let's put one TextBox, Label And Button.

By clicking on the button, the second form will open and the text from the text field of the main form will be transferred to the text field of the second form. Initially, the second form looks like this:

Similar to the first one, it has the same controls. We don't need any more. The application entry point launches the main form:

Using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace From1FormTo2 ( static class Program ( // The main entry point for the application. static void Main() ( Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); ) ) )

The main form code looks like this:

Using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace From1FormTo2 ( public partial class MainForm: Form ( //second form SecondForm secondForm; //constructor public MainForm() ( InitializeComponent(); ) //data transfer event handler //from the main form to the second private void btn_mainForm_Click(object sender, EventArgs e) ( secondForm = new SecondForm(tb_mainForm.Text.Trim()); secondForm.ShowDialog(); if (secondForm.DialogResult == DialogResult.OK) tb_mainForm.Text = secondForm.ReturnData(); ) ) )

Accordingly, do not forget to connect the button to the event Click. Here, in the main form class, there is a field SecondForm secondForm, representing the second form object. When you click on the “Submit” button, a second form is created (the overloaded constructor is called, we will create it later) and launched using the method ShowDialog(). In this case, this method is suitable for us. Moreover, after this we make sure to check whether the second form was closed, but clicked on its button. If a button was clicked on the second form, then the first form should accept data from the second. This happens by calling the method ReturnData() in the second form.

Now the most interesting part is the code of the second form:

Using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace From1FormTo2 ( public partial class SecondForm: Form ( //overloaded constructor public SecondForm(string data) ( InitializeComponent(); tb_secondForm.Text = data; ) //data transfer event handler //from the second form to the main one private void btn_secondForm_Click (object sender, EventArgs e) ( this.DialogResult = DialogResult.OK; ) //public method for accessing //the text field of this form public string ReturnData() ( return (tb_secondForm.Text.Trim()); ) ) )

As you can see, there is a single constructor overload that accepts a string type. Remember that we are trying to transfer text from a TextBox. In the constructor, the components are scheduled to be initialized and the text of the text field is set to the transmitted value from the first form. Next, by subscribing to the event Click for the button of the second form, we created a handler btn_secondForm_Click, which simulates the operation of the “Ok” button of any dialog box. Thus, by clicking on the “Submit” button (of the second form), we execute the condition

(secondForm .DialogResult == DialogResult .OK)

The first form, therefore, calling the method secondForm .ReturnData(), we set the text field of the first form to the value of the text field of the second form.

The operation of this method, I think, no longer requires explanation. It simply returns the text from a single text field, while keeping it private.

As a result, we transferred data to the second form from the first and from the second to the first without violating the principles of encapsulation.

Try entering the text “aaa” into the text field of the first form and clicking the button. You will see this text in the text field in the second form that opens. Try changing the text to “aaa ppp” and click on the button. You will see how, after closing the second form, this text will appear in the text field of the main form.

Now, I think you will be able to transfer data between forms more correctly. In the next article we will talk about how to do it in ASP.NET applications.

Sometimes it is necessary to access the elements of one form from another during program execution. For example, there is a form Form1, from it we open another Form2 and now, working in Form2, we need to access the elements of the parent form Form1. I found several ways to do this.

1st method. Passing a reference to a public variable.

Namespace WindowsApplication1 ( public partial class Form1: Form ( public Form1() ( InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( Form2 frm = new Form2(); frm.but1 = this.button1; // send link to the button in the form Form2 frm.ShowDialog(); ) ) )

In Form2, the variable to which the link was passed will now correspond to button1 from Form1

Namespace WindowsApplication1 ( public partial class Form2: Form ( public Button but1; // this variable will contain a link to button1 from Form1 public Form2() ( InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( but1. Text = "test"; // change the text on the button button1 of Form1 ) ) )

2nd method. Passing the link to the child form.

The essence is approximately the same in the 1st method. When opening Form2, we pass into it a link to the element that we plan to change later.

Namespace WindowsApplication1 ( public partial class Form1: Form ( public Form1() ( InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( Form2 frm = new Form2(this.button1); // pass a link to the button to the form Form2 frm.ShowDialog(); ) ) )

Now in Form2 we need to create a variable that will contain a link to this button and through it we will access the button on Form1 (lines 5,7,9 and 15).

Namespace WindowsApplication1 ( public partial class Form2: Form ( private Button but1; // this variable will contain a link to the button button1 from the form Form1 public Form2(Button but) // get a link to the button in the variable but ( but1 = but; // now but1 will be a link to button button1 InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( but1.Text = "test"; // change the text on button button1 of Form1 ) ) )

3rd method. Access to the entire parent form.

To do this, you need to make changes in several files, but at the same time we will have access to all elements of the parent form and do not need to pass a link to each element, as in method 1.

Step 1. In file Program.cs create a public variable f1 (line 5).

Namespace WindowsApplication1 ( static class Program ( public static Form1 f1; // variable that will contain a link to the form Form1 static void Main() ( Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1() ); ) ) )

Step 2. Opening Form1.Designer.cs and in it, for elements that will need to be accessed from another form, we change private on public. For example, let's make button1 on Form1 available for changes.

Public System.Windows.Forms.Button button1; // replaced private with public

Step 3. When creating Form1, we assign variable f1 a link to this form (line 7)

Namespace WindowsApplication1 ( public partial class Form1: Form ( public Form1() ( Program.f1 = this; // now f1 will be a link to the form Form1 InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( Form2 frm = new Form2(); frm.ShowDialog();

Step 4. Now from absolutely any form or from any class you can access the button1 element located on Form1 like this: Program.f1.button1. For example, let the button in Form2 change the text of the button on Form1:

Namespace WindowsApplication1 ( public partial class Form2: Form ( public Form2() ( InitializeComponent(); ) private void button1_Click(object sender, EventArgs e) ( Program.f1.button1.Text = "test"; // Change the text on the form button Form1 ) ) )

By admin.

Learning C# is slow. but it continues faithfully. Just recently I
gave an example of how to open another from one form in Visual C#. In principle, everything is simple.

Today the following task appeared: launch a modal form from the main form of the application; when closed, this form must pass some data (text, property values, etc.) to the controls on the main form. It is not possible to solve this problem using the method described in the previous post about forms, because in this case we simply create a new form object with new values ​​for all properties. Fortunately, C# has a wonderful garbage collector... But the point is not the collector, but how to open a child form in C#, and then get back to the main form from it?

To begin with, let's set the initial (initial) data.

So. We have the main application form:

This form also contains a TextBox with the name TBDialog and a Button button on which we should click:

  1. Pass the value of the Text property from TBDialog to TBMain;
  2. Close fDialog;

Now let's look at the whole process in order.

First, it's always worth remembering that by default all properties, variables, and methods in C# are assigned a modifier private– therefore, in order to get from the second form to the control on the first, we need to set a modifier for TBMain public on one's own. To do this, select the TBMain element in the form designer, go to the properties window and change the property value Modifiers With private on public

Now TBMain will be visible in other objects. Let's move on. In order to open the form in modal mode, we need to use one of two options for the ShowDialog() method:

public DialogResult ShowDialog() ; public DialogResult ShowDialog(IWin32Window owner) ;

In the first case, the method displays the form as a modal dialog box with the current active window set as the owner, and in the second, we can independently specify which form will become the owner for our modal window.

For example, let's use the second version of the ShowDialog() method and show the second form modally. To do this, we will write the following:

Here I used the keyword again this , which points to the current object, i.e. set the main form as the owner ( fMain). Now let’s move directly to solving our problem and answer the question: how to pass value from one form to another? Each control has a remarkable property Owner – which points to the parent:

Now you can run the project and make sure that the text from the TextBox on the child form transfers perfectly to the TextBox on the first one. Just in case, I’m posting the source code of the project discussed in the example.

Last updated: 10/31/2015

To add another form to the project, right-click on the project name in the Solution Explorer window and select Add->Windows Form...

Let's give the new form some name, for example, Form2.cs:

So, we have added a second form to our project. Now let's try to implement interaction between two forms. Let's say that the first form will call the second form when the button is clicked. First, let's add a button to the first form, Form1, and double-click on the button to go to the code file. So, we will be taken to the button's click event handler, which is created by default after double-clicking the button:

Private void button1_Click(object sender, EventArgs e) ( )

Now let's add the code for calling the second form to it. Our second form is called Form2, so first we create an object of this class, and then to display it on the screen we call the Show method:

Private void button1_Click(object sender, EventArgs e) ( Form2 newForm = new Form2(); newForm.Show(); )

Now let's do the opposite - so that the second form affects the first. While the second form does not know about the existence of the first. To fix this, you need to somehow transfer information about the first form to the second form. To do this, we will use passing a link to the form in the constructor.

So let's move on to the second form and go to its code - right-click on the form and select View Code. For now it is empty and contains only a constructor. Since C# supports method overloading, we can create several methods and constructors with different parameters and call one of them depending on the situation. So, let's change the code file of the second form to the following:

Using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace HelloApp ( public partial class Form2: Form ( public Form2() ( InitializeComponent(); ) public Form2(Form1 f) ( InitializeComponent(); f.BackColor = Color.Yellow; ) ) )

In fact, we just added a new constructor here, public Form2(Form1 f) , in which we get the first form and set its background to yellow. Now let's move on to the code of the first form, where we called the second form and change it to the following:

Private void button1_Click(object sender, EventArgs e) ( Form2 newForm = new Form2(this); newForm.Show(); )

Since in this case the keyword this represents a reference to the current object - the Form1 object, then when creating a second form it will receive it (the link) and control the first form through it.

Now, after clicking the button, a second form will be created, which will immediately change the color of the first form.

We can also create objects of the current form:

Private void button1_Click(object sender, EventArgs e) ( Form1 newForm1 = new Form1(); newForm1.Show(); Form2 newForm2 = new Form2(newForm1); newForm2.Show(); )

When working with several forms, you must take into account that one of them is the main one - which is launched first in the Program.cs file. If we have a bunch of forms open at the same time, then when we close the main one, the entire application closes and along with it all other forms.

Despite the fact that my opinion about Microsoft's Visual Studio is still the same, sometimes you have to do something on it. If we come to terms with the fact that we write, in fact, not in C++, but in the so-called C++/CLI, working with familiar visual components will not be so different from the same Borland environments. But it can create problems, compared to Builder. Let's consider 3 typical situations of working with an application containing more than one form. The example environment is free Visual C++ 2010 Express, it is assumed that the main form has the default name Form1.

An example of constructing and programmatically calling a form

This code can be executed, for example, by clicking a button in the main form Form1.

Form^form2 = gcnew Form(); Button^ button2 = gcnew Button(); button2->Text = L"OK"; button2->Location = Point(10,10); form2->Text = L"My window"; form2->HelpButton = true; form2->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; form2->StartPosition = FormStartPosition::CenterScreen; form2->Controls->Add(button2); form2->ShowDialog();

To add a handler for clicking a programmatically generated button button2, just write before the last line of code:

Button2->Click += gcnew System::EventHandler(this, &Form1::button2_Click);

Before the form2->ShowDialog() or form2->Show() method is called;

In this case, the handler code is located in the current module Form1.h:

Private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) ( MessageBox::Show("Here"); )

Call another form from the main form

In the menu, select Project - Add a new element - Form - name Form2

Let's add an operator

#include "Form2.h"

before the first namespace in Form1.h (that is, at the very beginning of the file).

Let's include a pointer to the class instance in the public section of the Form1 class:

Form2^F2;

Let's add the code where we need to create and call the second form:

F2=gcnewForm2(); F2->Show();

To programmatically delete the second form, the following code is suitable:

Delete F2;

It should be noted that the pointer stores the address of only one form, the one that was created last. If we sequentially create several forms using this code, only the last one will be deleted. Alternatively, try the shape array described below.

Let's describe the necessary data in the form class Form1 (here the name and namespace of the Tabulator project, if necessary, replace with your own):

Static const int MAX_FORMS = 100; //Maximum number of forms int FormCount; //Form counter array ^F2; //Pointer to an array of forms

Then we initialize the data using the Load event of the main form:

FormCount=0; F2 = gcnew array (MAX_FORMS);

Then we implement the code to create the next form

If(FormCount Show(); ) else MessageBox::Show("Too many forms!");

and its removal:

If (FormCount) ( delete F2; FormCount--; )

If we want to create child forms not separately, but inside the parent form, then in the properties of Form1 we need to indicate that it is an “ancestor” (set the IsMdiParent property = true), and before showing the child form using the F2->Show() operator, mark it as a child Form1:

F2->MdiParent = this;

Call a parent form method from a child form

We can hardly do without using .cpp files, which is not a bad thing - writing code in .h files generally breaks the correct C system :)

Let's describe the process step by step.

1) There are 2 forms - Form1 and Form2, on Form1 there is a Button (button1, will open the second form) and Label (label1, here we will change the text). On Form2 - button1, when clicked, the text in label1 will change.

2) Since we need to have access to the second from the first form, and from the second to the first, the problem of cross-references will arise (when Form1.h refers to Form2.h, which, in turn, again refers to Form1.h) . In order to avoid this, we will move the code of the first form (Form1), which will have access to the second form (Form2), from the .h file to the .cpp file. Thus, you need to create a file Form1.cpp.

3) Declare a public Set method in Form1.h so that you can change the text of label1 (the code can be written at the end of the file, after #pragma endregion):

Public: void Set(String^ text) ( label1->Text = text; )

4) In the Form2.h file we include Form1.h (at the beginning):

#include "Form1.h"

and create a constructor that will accept and save a link to the first form for further use:

Form2(Form1^ parent) ( InitializeComponent(); parentForm = parent; ) //you can write a link immediately below: private: Form1^ parentForm;

5) On clicking the button in Form2, we will call the Set method of the parent form:

Private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) ( parentForm->Set("hello from form2"); parentForm->Show(); this->Hide(); )

6) It remains to open the second form in the first form. To do this, we move the button click handler from Form1.h to Form1.cpp , and in the .h file we leave only its declaration.