I am working a WinForm Application. I have a couple of forms on it. I want to be able to access my main form from any child form. I was able to do that through a custom button function and capture the Form_Closing event. I have one problem though which I'll explain below.
The code on the main form is as follow:
ChildForm form = new ChildForm(); // Create new Child Form instance
form.Show(); // Show Child form
this.Hide(); // Hide Main form
Using "this.Hide();" means that the main form still exists in memory and is still working, it's just hidden which is what I want.
The code on the child form
MainForm form = new MainForm(); // Create new Main Form instance
form.Show(); // Show Main Form
this.Close(); // Close Child Form
This is all well except on my second code block (Child Form directly above), the first line of code, creates a new instance of the main form. That is my problem, I don't want to create a new instance of that form, I want to show the already existing hidden instance (The main form I hid in the first block of code above).
I tried the following code on the Child form:
this.Parent.Show();
But I got this runtime error message:
"System.NullReferenceException was unhandled: Message=Object reference not set to an instance of an object".
I understand what the error means, I just don't the code to create an object reference to that main form or how to reference it in any sort.
Any tips please?
Thanks ahead.
You can make a constructor for your other forms that takes in a window as a parameter
private Form MyParent { get; set; }
public Form1(Form parent)
{
MyParent = parent;
}
MyParent.Show();
where MyParent is a property of the form
you can call this via new ChildForm(this)
Edit
I just looked, not sure why I can't use a constructor for an IWin32Window but Show has an overload that takes one in which will set the Owner to a parent form
new ChildForm().Show(this);
ChildForm.Owner //returns MainForm (parent)
That should do it. Because these are single thread forms, the function will wait till you close the form before proceeding further.
ChildForm form = new ChildForm(); // Create new Child Form instance
this.Hide(); // Hide Main form
form.ShowDialog(); // Show Child form, wait for closing
this.Show();
You can also attach ChildForm closing event to function in MainForm.
public MainForm()
{
ChildForm form = new ChildForm();
form.FormClosed += OnClosed;
}
public void OnClosed(object sender, EventArgs e)
{
this.Show();
}
Related
I have two forms. I show my second form with this code:
Form2 f = new Form2();
f.ShowDialog();
I need to understand when focus returns to main form. I tried Activate event but that's not it.
The call to ShowDialog() is blocking the parent form.
When your code exit from ShowDialog() your current form become active again,
For example:
using(Form2 f = new Form2())
{
// At the moment of the call of ShowDialog, the Net Framework start its work to
// pass the focus to the first control in the Form2 instance
if(DialogResult.OK == f.ShowDialog())
{
// Form confirmed, do your stuff
}
}
// At the end of the using block the parent form is again the active form with the focus on
// the button that has started this process (or the last control that had focus)
When you type
Form2 f = new Form2();
f.ShowDialog();
it waits until you manually close the Form2 instance and then returns to the main form. This happens if you use ShowDialog() method.
In some cases, where you just want to pop-up another form for a fraction of a second and return to the main form you should use formInstance.Show() method. The Show() method does not wait for the second form to be closed, it executes immediately and passes the control to the next statement after the Show() statement.
Hope you understood it.
I have the following problem:
I open multiple modal forms in a stack (for example, form1 opens modal form form2 which in turn opens modal form form3, etc.). I would like to hide the entire stack.
I tried calling the Hide method or setting the Visible property on the parent, but this only hides the parent. I also tried hiding every form individually, but then I have to call ShowDialog on each of the forms which locks the thread in which I call the aforementioned method.
Is there be a way to set the modal dialogs so that they inherit the status of the parent and get hidden in a cascade just by setting the property on the first form?
I'm also open to other suggestions.
To re-show a form you hid by setting obj.Visible = false just set obj.Visible = true, not ShowDialog.
ShowDialog initiates a message loop, which will cause confusion since the dialog is already running a message loop.
Since you're talking about modal dialogs, it would be the last one opened that would commence this action. Open every form as in the following example, and then Hide() that last one.
public partial class Form1 : Form
{
Form2 frm2 = new Form2();
public Form1()
{
InitializeComponent();
frm2.VisibleChanged += frm2_VisibleChanged;
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
frm2.ShowDialog();
}
void frm2_VisibleChanged(object sender, EventArgs e)
{
if (frm2.Visible == false) Hide();
}
}
i have 3 forms.
main_frm is MDI
app_frm is child MDI
progress_frm just a form that shows progress of app_frm
in the progress_frm form i have a button named "cancel" that closes the progress_frm form. Then have the following event on closing the progress_frm.
private void frm_progress_Closing(object sender, FormClosingEventHandler e)
{
Form currentForm = Form.ActiveForm;
Form app_frm_temp = currentForm.ActiveMdiChild;
app_frm_temp.Dispose();
}
I am expecting that the form app_frm will close and terminate anything it was doing. but that does not happen.. only the progress_frm form closes, and i still see app_frm running with the hour glass and still running it's process/thread.
My goal is that if a user wants to abort and close the process that app_frm started, they would be able to terminate and close app_frm from progress_frm?
after the feedback below i tried the following, my form was not hitting the closing event because i copied and pasted it from another form , i then went on the design portion of progress_frm and made an event sorry for confusiong on that :( :
private void progress_frm_FormClosing(object sender, FormClosingEventArgs e)
{
Form currentForm = Form.ActiveForm;
foreach (Form frm in currentForm.MdiParent.MdiChildren)
{
if (frm.GetType() == currentForm.GetType())
{
frm.Focus();
return;
}
}
}
i get a null exception "object reference not set to an instance of an object" when the loop accesses currentForm.. remember my i am the progress_frm which is not part of the MDI config... i am trying to reference and close/terminate the child form app_frm whose parent is main_frm... i know that currentForm is main_frm, but not sure why it will not find the child form so i can reference it?? i tried changing loop to "currentForm.MdiChildren" and still got same null reference exception...
i thought i understood MDI concept, but now am getting confused on how to be able to reference them properly
Are you sure that your app_frm_temp object refers to the opened instance of app_frm Form? If it is then on FormClosing event of your app_frm you have to properly send the closing notification to your process/thread, a nice example is given here for stopping the background thread/process before closing the form: How to stop BackgroundWorker on Form's Closing event?
But before this just to make sure you are refering to correct instance of Form, this is how you can loop through all opened MDI childs and get the reference to one you are interested in:
foreach (Form frm in this.MdiParent.MdiChildren)
{
if (frm.GetType() == app_frm.GetType())
{
frm.Focus();
return;
}
}
I have a simple problem: I have a main form in win-forms/c#. It has a listbox bound to a database.
When I click a button a new form is created.
When I click a button on the child form, I want to call a method that exists in the main form, that updates the list box or alternatively when the child form closes, to call that function.
Is this possible??
There are many ways to achieve this, but here's a simple way. In your main form, when you create and show a child form, do it like this:
ChildForm child = new ChildForm();
child.Show(this); // this calls the override that takes Owner parameter
Then, when you need to call a method in the main form from the child form, use code like this (assumes your main form is of type MainForm):
MainForm parent = (MainForm)this.Owner;
parent.CallCustomMethod();
A more complex way would be to use a form of dependency injection, where you would pass in a reference to the parent form (or more properly, to its interface) in the constructor of the child form. But the above way is simple and probably effective enough for your purposes (and it actually is a form of dependency injection itself, sort of).
Scenario 1: Call a method in Parent Form on click of button in child form.
Create an Event in Child Form. Raise that event on some Button Click etc. Subscribe to that event in your Parent Form and call the parent's form method inside that.
Scenario 2: Call a method in Parent Form when Child Form is closed.
Handle the FormClosed or FormClosing event of Child Form in the Parent form and call the parent's form method inside that.
ChildForm frm = new ChildForm();
frm.FormClosed += new FormClosedEventHandler(frm_FormClosed);
void frm_FormClosed(object sender, FormClosedEventArgs e)
{
//Call your method here.
}
When my program runs it closes form1 after a few seconds. Depending on what happened during form1's lifespan I may want to open form2. Normally I would just make a new instance of form2 and use the show() method. But form2 is then a child of form1 and then also closes. Does any body have an idea on how to get this to work? thanks.
For multi-form applications I tend to have one form that is the "main" form, which opens up the sub forms.
The main form is the one that gets started with Application.Run(...)
In your case you might want to have a blank form that can be the controller, and have Application.Run call that.
That form can then start instantiate your Form1 and run it.
e.g.
public ControlForm : public Form
{
Form1 form1;
Form2 form2;
public ControlForm()
{
form1 = new Form1();
form2 = new Form2();
}
public void Start() // or something similar
{
form1.ShowDialog(); // will block showing the form, or you can do other tricks
// to show the form here
if(form1.someFlag) form2.ShowDialog();
}
}
This is just "psudo-C#" code, but hopefully the concept makes sense
Then your main function can just run "ControlForm"
Its just a concept you might want to try
You can open a new form in your application's bootstrapper (main method). You will want to call Application.Run(yourFormHere). You would have two of these in a row in the order you want to show the forms. You could store the results of the first form in some static location and check that before showing the second form.
I ended up doing this:
Auth f = new Form1();
Application.Run(f);
if (f.authed)
{
Application.Run(new Form2());
}
I don't think that your problem is that the Form2 instance is a child form of the Form1 instance, but rather that the Form1 instance is your applications main form. That will make your application quit whenever Form1 closed. One way to prevent this is to alter the main method to not set Form1 as the main form (see here for details on that).