I have a Form (form3)which could be opened from two other forms. Form1 and Form2.
how can I get which one is the parent of the form3?
The term "parent" has a very strict definition in Windows. The Form class derives from Control like all UI classes do, but it is pretty distinct, it is a top-level window. Very unlike the other controls, like Button and TextBox, they are child windows inside a parent window. The parent of a Form is the desktop window, pretty unlikely that you are interested in that one.
So it is pretty meaningless to talk about "the parent of Form3", it is the same parent as Form1 and Form2 and it doesn't help you at all to distinguish which one might have displayed the Form3 window.
Windows does have a way to associate two top-level windows with each other, it has the notion of an owner window. It is meant to implement a tool window or a dialog, an owned window is always displayed on top of its owner and is minimized along with its owner. Creating an owned window is simple:
var toolWindow = new Form3();
toolWindow.Show(this);
This Show() overload takes an argument that indicates its owner, this can be a reference to a Form1 or Form2 object, depending on where this code appears. Inside the Form3 class, you can find the owner back by using the Owner property.
Which is fairly unlikely what you are really talking about, Winforms is frequently a programmer's first introduction to object-oriented programming and dealing with object references is often confounding. If you need a reference to a logical parent in Form3 then just write the code so you pass that parent. Which you do by giving the Form3 class a constructor:
private Form logicalParent;
public Form3(Form parent) {
InitializeComponent();
logicalParent = parent;
}
And creating the window in Form1 or Form2 just takes:
var form = new Form3(this);
form.Show();
You can further improve this code in an object-oriented way by designing a base class for Form1 and Form2, one that has members in common that a class like Form3 would be interested in. Or better yet, an interface that both Form1 and Form2 implement, that reduces the coupling significantly. Last but not least, use events to allow Form3 to notify its logical parent. Probably what you are really looking for.
You can access the Parent form from the Child like this,
Say MainForm is the Form1
MainForm parent = (MainForm)this.Owner;
Or If you want to find the Parent from the hierarchy,
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;
}
Inside your Form3 you can do this:
var form1 = this.Parent as Form1;
if(form1 != null)
{
//form1.Text
}
var form2 = this.Parent as Form2;
if(form2 != null)
{
//form2.Text
}
Normally I get a name of Parent of control via
MessageBox.Show(control_Name.Parent.Name);
but now we are finding the Parent of a form, so we cannot use the same method because we don't even need to have real Parent and Client relationship to call a Form. So we will have NullReferenceException when we do
MessageBox.Show(this.Parent.Name);
in Form3.
By doing these in Form 1 and Form2 and Form3, I can call the Form3 from both forms.
Form1
Form3 frm3;
public Form1()
{
InitializeComponent();
frm3 = new Form3(this);
}
private void button1_Click(object sender, EventArgs e)
{
frm3.Show();
}
Form2
Form3 frm3;
public Form2()
{
InitializeComponent();
frm3 = new Form3(this);
}
private void button1_Click(object sender, EventArgs e)
{
frm3.Show();
}
Form3
public Form3(Form parent)
{
InitializeComponent();
}
As my conclusion, if the Parent form can only have one, then both of Form1 and Form2 is not Form3 parent Form because either one is not exist but the other one still can call Form3 out. If the Parent form can have more than one, then I think both of Form1 and Form2 are parent forms of Form3.
By the way, if the Parent Form minimized, the Child Form also minimized, then we can make Form1 as Parent Form (or actually owner form) of Form3
Form1
Form3 frm3;
public Form1()
{
InitializeComponent();
frm3 = new Form3(this);
this.AddOwnedForm(frm3);
}
OR
we set the owner of Form3 to the Form who calling it by
Form3
public Form3(Form parent)
{
InitializeComponent();
this.Owner = parent;
}
If you are not agree with me, please give me clear definition of Parent form and Child form.thanks. I try to explain from my point of view and hope someone correct me if I am wrong.
Related
I am running two forms simultaneously and I am trying to resize Form1 by calling a Form1 method with an event in Form2. With the following code the proper size values are displayed in the console, but the size of Form1 does not change. I have tried a number of approaches but I don't see why this does not work.
In Form1:
public void ResizeForm()
{
Console.WriteLine(this.Size.ToString());
this.Size = new System.Drawing.Size(600, 300);
}
In Form2:
private void ResizeCheckbox_CheckedChanged(object sender, EventArgs e)
{
Form1 form = new Form1();
form.ResizeForm();
}
You should pass the instance of the current Form1 to the second form. Add an instance in Form2 and then get it from Form1
Form2
Form1 _form1;
public Form2(Form1 form1)
{
InitializeComponent();
_form1 = form1;
}
private void ResizeCheckbox_CheckedChanged(object sender, EventArgs e)
{
_form1.ResizeForm();
}
Then open Form2 in the main form like this.
Form2 form2 = new Form2();
form2.Show((Form1)this); //I'm not sure if you need to cast "this" to From1
Form1 form = new Form1(); creates a new form, resizes it, and then forgets it. So, this is completely pointless. The ResizeForm() method does get invoked, but on the wrong instance of Form1. From your description, you should have some other instance of Form1 somewhere, the instance that you are actually displaying to the user. You need to access that instance from within Form2. If you do not have access to the correct instance of Form1 from within Form2, you must somehow pass it, so that Form2 has it. Creating a new instance of Form1 is not going to resize the original instance of Form1.
I have a program with two forms.
The second form, Form2 in which I want a few labels initialized with values from the main form.
The code:
public Form2()
{
InitializeComponent();
Form1 mainForm = (Form1)this.Owner;
lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
}
For some reason this does not work in the Form2() section, this.Owner is null. But if I was to place the code in an event method it works just fine.
How can I fix that?
The second form shouldn't need to even know about your main form in the first place. Even if it did, it's an extremely bad idea to be reading into its internal controls.
Instead your second form should have public properties through which it can accept the data that your main form wants to provide to it, without exposing any of its internal controls, and the main form can set those properties using the data from its controls. You could also potentially use parameters to the constructor instead, if you have just a bit of data, and that is the only time you need to provide it.
public class Form2
{
public string Name
{
get { return lblName.Text; }
set { lblName.Text = value; }
}
}
public class MainForm
{
public void Foo()
{
Form2 child = new Form2();
child.Name = mainForm.gvRow.Cells[2].Value.ToString();
child.Show();
}
}
This code is executed when the Form2 form is created. The Owner isn't set yet (and, presumably, the data isn't present yet). If you put it in the VisibleChanged event handler - it will be executed when the Owner and data are (presumably) present.
Use the Load Event. The Owner is only initialized after you Show the form, which then in return raises the Load Event.
Owner isn't set until the form is shown - i.e. in ShowDialog, not during the constructor. You should pass the parent as a parameter in the constructor:
public Form2(Form1 mainForm)
{
InitializeComponent();
lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
}
That's because the Owner is not initialized yet in the Form2 constructor, set your code in your Form2_Load event
Use the Form.Show(IWin32Window) overload to pass the owner to the child form.
http://msdn.microsoft.com/en-us/library/szcefbbd(v=vs.110).aspx
You need to set the Owner property yourself
As an alternative you could pass a reference to Form1 to the Form2 constructor. In the code that opens Form2 you probably have something like this:
var form2 = new Form2();
form2.Show();
You could replace that with:
var form2 = new Form2(this);
form2.Show();
In Form2 you'd add a constructor overload:
public Form2(Form1 owningForm)
{
InitializeComponent();
Form1 mainForm = owningForm;
lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
}
If different "owning forms" are possible you may need to define an interface instead of passing Form2.
In my application I have problem with some windows forms. They are sometimes fell down under another window.
Is there some Z-coordinate for Form? Or how is this working?
Thank you.
EDIT: I should add, that I'm using Smart Client Software Factory.
You can use the Form.Show(IWin32Window owner) method to spawn a form as a child of another form, which will always keep it above that form.
For example:
class Form1 : Form
{
public Form1()
{
InitializeComponent();
var f2 = new Form2();
f2.Show(this);
}
}
class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
}
When an instance of Form1 is created, it will create and show an instance of the Form2 class as a child. Form1 will be behind Form2 regardless of which form has focus.
EDIT: I took some screenshots of the effect, complete with labels that responded to the GotFocus and LostFocus events of each form to demonstrate in case the lovely blue border wasn't enough:
Hi I am using windows forms in C#. I am trying to modify the visible property of a picture from main form to another. Initially, the visible property of the picture box is set to false. On a button click from another form, the visible property of the picture box is modified to true.
This is the code written in the Form2 method:
private void button_Click(object sender, EventArgs e)
{
public Form1 frm1 = new Form1();
frm1.pictureBox.Visible= true;
}
Form1 is an instance type, so when you do
public Form1 frm1 = new Form1();
frm1.pictureBox.Visible= true;
you're really just creating a new instance of Form1 completely unrelated from your original Form1, changing a picture-box's visible property on it, and then discarding it.
What you can do, is put a reference to the "parent" Form1 inside your Form2 class.
Here's an example
public partial class Form2 : Form
{
public Form2(Form1 parent)
{
InitializeComponent();
this.Parent = parent;
}
Form1 Parent;
private void button1_Click(object sender, EventArgs e)
{
Parent.pictureBox.Visible= true;
}
...
}
there you create an instance of a form :
public Form1 frm1 = new Form1();
This is then obviously NOT the form you already may have in your page, which you could simply access by its ID.
According to your written code it will create new instance of the desired form, and NOT take the existing open form. Hence to identify the existing open form containing target picture box you need the target form and controlling form be related by like Parent form or MDI Parent Form.
Assuming case of MDI Parent Form (i.e. Controlling form is MDI Parent of Target Form), you need following codes to identify to existing open form:
foreach (Form frm in MdiChildren)
{
if (frm is myTargetForm)
{
//do your code to find control using id of picture box and change the required properties
}
}
In my main form (form1) I have checkboxes that when checked should also check the corresponding box in form2. I also want if checkboxes in form2 are checked they check the corresponding boxes on form1. The problem that I believe I am encountering is that form1 can make an object of form2 to reference, however if I instantiate an object of form1 within form2 I believe it creates an infinite loop? Any help figuring this out is appreciated.
Form1 creates an object of form2:
Form2 formSettings = new Form2();
Now when I have an event I can update form2:
public void logScanResultsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (logScanResultsToolStripMenuItem.Checked)
{
formSettings.chbxLogScanResults.Checked = true;
}
else
{
formSettings.chbxLogScanResults.Checked = false;
}
}
But if I try to do something similar in Form2:
Form1 form1 = new Form1();
So that I can reference form1's menu item from within form2(formSettings) I end up creating an object (form1) that calls to make an object of Form1, which within Form1 includes a call to create an object of Form2 and thus an endless loop.
You shouldn't create an instance every time a checkbox is checked off. You need to maintain the instances alive and hide/show them as needed. Also, the constructor of one of the forms should receive the other one as parameter in its constructor so they can reference each other.
Hopefully this is clear enough. It isn't a straight out answer as you really dont have much detail in your question.
Basically you have two forms, Form1 and Form2, which will be throwing events (OnChangeEvent?) on the change of some checkboxes.
Form1 listens for events from Form2 and Form2 does the same from Form1.
If Form1's event listen receives a OnChangeEvent and changes its checkbox then it should raise an OnChangeEvent. If on the other hand it doesn't change its checkbox (as it already has the correct value) then it should not raise an OnChangeEvent.
In the body of Form1 you need to declare Form2 to hold an instance of it for referencing and to open it. When you call the Form2.Show method from Form1, you will pass a reference of itself to Form2 which you then can use to gain access back to Form1.
public partial class Form1 : Form
{
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
}
private void form1Button_Click(object sender, EventArgs e)
{
form2.Show(this);
}
private void form1CheckBox_CheckedChanged(object sender, EventArgs e)
{
form2.ChangeCheck(form1CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form1CheckBox.Checked = isItChecked;
}
}
In Form2 you can now reference Form1 as the owner.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void form2CheckBox_CheckedChanged(object sender, EventArgs e)
{
((Form1)this.Owner).ChangeCheck(form2CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form2CheckBox.Checked = isItChecked;
}
}