I know that the title might seem silly, couldn't think of something better, sorry.
I have 2 Forms (C#), the main-form holds an instance of the second.
Is there a way to.. get access to the running instance of Form1 (The entry point) and to his properties from the instance of form2?
Everybody tells me to learn OOP.
I did, a long long time ago, and I still don"t get it.
When the main form instantiates the second form, it could pass a reference to itself to the constructor of the second form.
Thus, the second form will have access to the public members of the first.
EDIT
In the Form1 you instantiate Form2 somewhere and pass it a reference to Form1 in ctor:
Form2 f2 = new Form2(this);
In the class definition of Form2 add a field:
private Form1 m_form = null;
In the constructor of the second form set that field:
public Form2(Form1 f)
{
m_form = f;
}
Then, everywhere in your Form2 you have access to Form1 through the means of m_form
You probably instanciated Form2 from within Form1. After instanciating and BEFORE showing it you could set a property on Form2 that refers to Form1 like this:
Form2 f2 = new Form2();
f2.TheParent = this;
f2.Show();
Of course you have to add the TheParent property to the Form2 class to be able to do that.
Warning: although it is possible this way a better solution might be to create a seperate object that holds all required/shared data andd pass that object to each form in a similar way. This will prevent your code from becoming too coupled.
One approach to this can be creating an owner-owned relationship.
// Create a form and make this form its owner
Form ownedForm = new Form();
ownedForm.Owner = this;
ownedForm.Show();
or as a shortcut, you could pass the owner form as an argument to an overload of the Show method, which also takes an IWin32Window parameter
ownedForm.Show(this); // established owner-owned relationship
Then you could access the main form properties like this
((MainForm)this.Owner).ownerVariable;
In order for this variable/method to be accessible, it has to have the internal protection modifier.
Related
In my program I have two forms. The main form and a form where you fill in extra information. What I'm trying to do is to write out the information given on the second form on a list box when the 'ok' button is pressed.
Currently this is what I have:
Main form:
public void writeLine()
{
foreach (var item in VarClass.listItems[VarClass.count - 1])
{
listBox1.Items.Add(item.ToString());
}
}
Second form:
Form1.writeLine();
As it, I get the following error at 'Form1.writeLine();'
"An object reference is required for the non-static field, method or property..."
I can kinda fix this by making 'writeLine()' static in the main form, but then I get the same error on 'listBox1' in the main form. How do I fix this?
You should pass the reference of your main form to the second form and call the method on that reference. For example you can create a property on the second form like private Form _mainForm; and create a constructor of the second form to receive that reference and set to that field. After that you will be able to call _mainForm.writeLine() in your second form.
Create an instance of Form1 and call the method. Here is the code:
new Form1().writeLine();
There are a couple ways to handle this. One is for form2 to have a reference back to the calling form ideally through an interface rather than a reference to the concrete class.
Another option would be for Form2 to have an event that form1 could subscribe to that would inform form1 that form2 has some output.
Keep a reference to the second form from the first:
public MyFirstForm
{
...
public MyFunction()
{
MySecondForm secondForm = new MySecondForm();
// ... Open your form etc, look for when it's complete and then ...
// Read the values from the second form into the first
var MyValues = secondForm.getValues();
// Now populate the list-box with the information returned.
//for (my listbox)
}
}
In my parent Form I have this command where I add a child form into my main form:
AddChildForm(new Form2());
And in my Form2 I have a check box, and every time the check box is checked I have to change my Main form size, but I can't get to this work, only create a new form, like this:
Form1 main = new Form1();
main.Size = new System.Drawing.Size(482, 370);
main.ShowDialog();
If you don't want a new Form1 don't create it.
You probably need a reference to the real main form. This should be set at some time during or after opening it, but since all you show us is are 4 out of context lines we can't tell for sure..
And since we don't see the AddChildForm code it is even harder to guess.
However, chances are that you should pass a reference from the opening form to the opened form like this:
AddChildForm(new Form2(this)); // <--- pass in reference to the opening form!
And store it there like this:
Form1 mainForm = null;
public Form2(Form1 form1) // here we receive the main form reference
{
InitializeComponent();
mainForm = form1; // here we store it in a class level variable
//..
}
Now you can set the other forms Size:
mainForm.Size = new System.Drawing.Size(482, 370);
Of course you should keep a reference to the form you are opening in the main form as well, if you will need it. For this use something like this instead:
Form2 form2 = new Form2(this);
..
AddChildForm( form2);
i'm trying to make a second form and acces to all of the main form methods, values, etc... so what i do is:
public partial class Principal : Form
{
public Principal()
{
InitializeComponent();
}
...
And in one method i have...
private void agregarUsuarioToolStripMenuItem_Click(object sender, EventArgs e)
{
Form Form2 = new Form();
Form2.Show();
}
I suppose that in Form2 i could acces to all of what i have in my main form, but i wonder how to edit this Form2, how to put buttons or stuff, cause i didnt create a form, just another instance of Form().
First of all, you cannot access the values on the main form from the second form unless the second form has a reference to the first main form. They are completely separate instances. The second form is only another copy of the template (the type) that the first form was created from. All state or data in the first form is specific to the instance of the form (unless declared as static). All the controls and visual elements defined in the forms template are created in each of the instances from the template when the form is instantiated (when the constructor runs).
If you need the second form to refer to values on the first form, how to do this best depends on how, when and why.... If you only need to do this when the second form is constructed, and never again during the lifetime of the first form, then you can do it during construction ( Form Form2 = new Form(); ) if you have a reference to the first instance of the form. If you need access to the values on the first instance later as well (during the lifetime of the second instance), then you need to add a reference to the first instance as a private field or property of the form so that code on instances of the second form will always have a reference to the first instance. The best way os to make the second instance an instance of a derived (child) of the first form that has this additional property, and pass the reference to the first form in the constructor to of this second derived form type
public SecondForm: Principal
{
public Form PrincipalForm { get; set; }
public SecondForm(Principal principalForm)
{
InitializeComponent();
PrincipalForm = principalForm;
}
// other stuff
}
then, when you create the second instance, create an instance of SecondForm instead. It will look exactly like the first instance, (cause it derives everything defined on Principal), but will have this one additional property.
private void agregarUsuarioToolStripMenuItem_Click(object sender, EventArgs e)
{
SecondForm Form2 = new SecondForm(firstPrincipalForm);
Form2.Show();
}
now, everywhere on the second forms internal and public methods and code you will have a reference to the first form to do with as you wish
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Referencing control on one form from another form VB.NET
This is the question following my last question. Its the last on today :D When i have two forms. One is main with whole aplication and the secondone is just for settings. I need set one variable in Form2 and then after close this form, need Form1 to get this variable from form2. What is the easiest way to transfer this variable?
Create a Property in Form2:
public MyType MyVariable { get; set; }
Set the Property in Form2 (for example, in the form's Close event)...
this.MyVariable = ...;
...and read the property in Form1:
...
myForm2Instance.ShowDialog(); // this is where you show Form2
var theValueFromForm2 = myForm2Instance.MyVariable;
The easiest (though not the best) way is to store the value in a public property on Form2 which can then be accessed from Form1.
You can pass the information into Form2 in the constructor and have a property on Form2 that exposes the information. Then when you are done with Form2, you can say myForm2.ThePropertyThatHasTheData inside of Form1.
Not the "easiest way"... but generally speaking, the MVC pattern is the current state-of-the-art for organizing the UI layer of an application. You get a clean separation of UI from the data that the UI is displaying, and from flow control in your application.
See for example https://stackoverflow.com/questions/2406/looking-for-a-mvc-sample-for-winforms
Your two forms are views. So, you just need a model class.
Create a class called Model or similiar
Create a public property called Setting or similiar
Instantiate the model from Form1
Model m = new Model();
Pass the Model to Form2 during the constructor or set private member.
Form2 f = new Form2();
f.Model= m;
f.ShowDialog();
Let's say the setting is a text box on form2. Before the form closes, set the setting:
Model.Setting = this.textBoxSetting.Text();
Since the Model is an object and passed by reference, the model object in form1 will automatically be updated since it is the object referenced.
If you want the data to be shared throughout your application, consider making the Model static or follow the singleton pattern if only 1 model is used per application.
I want to update label of Form1 from Form2. So here's what I have:
// Form1
public string Label1
{
get { return this.label1.Text; }
set { this.label1.Text = value; }
}
// Form2
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
frm1.Label1 = this.textBox1.Text;
this.Close();
}
So the above code doesn't work. However, when I add the following:
frm1.Show();
after
this.Close();
in Form2 code, the Form1 obviously is being opened again (two windows). But I want it to update in the same window so I suggest this.Close() is unnecessary.
Anyone have any ideas?
In the button1_Click method, you're actually creating a new instance of Form1 and setting the Label1 property of that new instance. That explains why a second instance of Form1 is being shown on the screen when you add frm1.Show();. If you look at that second copy carefully, you'll see that it's label displays the correct value, but your original copy of that form retains its original value.
Instead, I assume that what you want to do is set the Label1 property for the existing instance of Form1 that is already displayed on the screen. In order to do that, you're going to have to get a reference to that existing form object.
Thus, this becomes a simple question of "how do I pass data between two objects (forms)", which has been asked countless times here on Stack Overflow. See the answers to these related questions:
Communicate between two windows forms in C#
Passing values between two windows forms
C# beginner help, How do I pass a value from a child back to the parent form?
Send values from one form to another form in c# winforms application
Try using singleton design pattern for that as I think the problem is when you using new
public class Form1Singleton {
private static final Form1Singleton INSTANCE = null;
// Private constructor prevents instantiation from other classes
private Form1Singleton () {
}
public static Form1Singleton getInstance()
{
if(INSTANCE ==null)
INSTANCE =new Form1Singleton();
return INSTANCE;
}
}
Now you can use the form easily only 1 form
private void button1_Click(object sender, EventArgs e)
{
Form1Singleton frm1 = Form1Singleton.getInstance();
frm1.Label1 = this.textBox1.Text;
this.Close();
}
I hope that solve your problem
BR,
Mohammed Thabet Zaky
Most probably: What you actually do is create a brand new instance of Form1 within the scope of Form2, while later in the control flow of your program another instance of Form1 is created and shown. Of course, in such a case you can't expect your label to be set correctly.
The best would be to decouple Form1 and Form2 from each other and instead pass only data along the control flow of your program.
When you say this.close that means all the values you set to that instance gets nullifies.
You can use delegate here, to set form values.
MVP pattern is good for this type of senario and also separate UI and business logic.
This thread is good reference:
UI Design Pattern for Windows Forms (like MVVM for WPF)