I have he following Form:
An Initialize Function that is called when the Form1 is created.
A button that opens another Form (Form2)
What I need is to call Initialize() not only when Form1 is created, but whenever Form2 is closed, since Form2 might have modified some stuff that makes Initialize need to be called again.
How can I detect when the form2 is closed?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Initialize();
}
void Initialize()
{
// Read a config file and initialize some stuff
}
// Clicking this button will open a Form2
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2().Show();
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
// some stuff that Form2 does which involves modifying the config file
}
}
You just need to add an event handler for the FormClosing event, this handler could be in your first form class and here you can call every internal method of that class
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2();
form2.FormClosing += childClosing;
form2.Show();
}
private void childClosing(object sender, FormClosingEventArgs e)
{
Initialize();
....
}
In addition to Steve's excellent answer, you may consider displaying Form2 as a modal dialog. This would mean code execution in Form1 STOPS until Form2 is dismissed. This may or may not work well with your application, we have no idea what it does.
At any rate, you'd use ShowDialog() instead of Show() like this:
// Clicking this button will open a Form2
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2().ShowDialog(); // <-- code STOPS here until form2 is closed
Initialize(); // form2 was closed, update everything
}
Related
I have a form called form1 with controls which are created during run-time.
When I press a button on the Form another Form loads called combat and form1 is hidden so that only 1 form (combat) is visible.
When I press a button on combat I want my form1 form the be shown. However I can't access it.
Here is what I've tried:
private void combatBtn_Click(object sender, EventArgs e)
{
Form combat = new Combat(this);
this.Hide();
combat.Show();
}
public partial class Combat : Form
{
public Combat(Form form)
{
InitializeComponent();
form.Show();
}
private void button1_Click(object sender, EventArgs e)
{
form.Show();
}
}
You need to store the parent form in a field so that you can access it outside the constructor.
public partial class Combat : Form
{
private form1 form; // Or whatever class you form1 is supposed to be
public Combat(Form form)
{
InitializeComponent();
this.form = form;
}
private void button1_Click(object sender, EventArgs e)
{
form.Show();
}
}
It's generally not advisable to pass an instance of a parent form to a child. In this case (as is often true) the code is actually simpler when you don't:
private void combatBtn_Click(object sender, EventArgs e)
{
Form combat = new Combat();
this.Hide();
combat.ShowDialog();
this.Show();
}
If you need to show the parent form before the child form is closed then you can do so through events:
in Combat add:
public event Action MyEvent; //TODO rename to a meaningful name
Fire the event in the button click handler:
private void button1_Click(object sender, EventArgs e)
{
MyEvent();
}
And then have your main form add a handler to the event:
private void combatBtn_Click(object sender, EventArgs e)
{
Combat combat = new Combat();
this.Hide();
combat.MyEvent += () => this.Show();
combat.Show();
}
At first I thought that it won't be a problem for me, but now I can't figure it out. So,
when I click Button1 in main form, form2 opens. Form2 is simple numeric keyboard, that user can enter some data. On form2 is also Save. When user clicks it, entered value should pass to main form and from that moment some event must happen in main form, which contains data from form2. Could you please give me some example or any kind of help? Thanks!
// code from main form to create form2
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of the Form2 class
Form2 settingsForm = new Form2();
// Show the settings form
settingsForm.Show();
string val = settingsForm.ReturnValue1;
MessageBox.Show(val);
}
//button save on form2
private void button13_Click(object sender, EventArgs e)
{
this.ReturnValue1 = "Something";
this.ReturnValue2 = DateTime.Now.ToString(); //example
this.Close();
//after this, some event should happen in main form !
}
There is a lot of solutions to do what you want; but I think one of these will resolve your problem.
1- Simple and easy: use public properties in Form2, initialize them when buttonSave get clicked, and access them in Form1:
Form2:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
YourDate = "something";
Close();
}
public object YourDate { get; private set; }
}
Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
var f2 = new Form2();
f2.ShowDialog();
var data = f2.YourDate;
}
}
2- A better way, is using events which is more flexible and professional programming friendly:
Form2:
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
}
// create an event of Action<T> which T is your data-type. e.g. in this example I use an object.
public event Action<object> SaveClicked;
// create an event invocator, to invoke event whenever you want
protected virtual void OnSaveClicked(object data){
var handler = SaveClicked;
if (handler != null)
handler(data);
}
private void button1_Click(object sender, EventArgs e){
// prepare your data here, -object, or string, or int, or whatever it is
var data = PrepareYourDataHere;
// invoke the event
OnSaveClicked(data);
Close();
}
}
Form1:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
// create an instance of Form2
var f2 = new Form2();
// add an event listener to SaveClicked event -which we have declared it in Form2
f2.SaveClicked += f2_SaveClicked;
f2.Show();
// or: f2.ShowDialog();
}
void f2_SaveClicked(object obj) {
// get data and use it here...
// any data which you pass in Form2.OnSaveClicked method, will be accessible here
}
}
UPDATE:
If you want to fire some events in form1, just after form2 closed, you can simply add a listener to Form2.FormClosed event:
// code from main form to create form2
private void button1_Click(object sender, EventArgs e) {
// Create a new instance of the Form2 class
Form2 settingsForm = new Form2();
settingsForm.FormClosed += SettingFormClosed;
// Show the settings form
settingsForm.Show();
string val = settingsForm.ReturnValue1;
MessageBox.Show(val);
}
void SettingFormClosed(object sender, FormClosedEventArgs e) {
// this method will be called automatically when form2 closed
}
here a sample how you can achieve this
//here I suppose that form1 is the mainform
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void UpdateMainForm(string updatedString)
{
//here you can update and invoke methods
//Once called you could raise events in your mainform
}
private void button1_Click(object sender, EventArgs e)
{
using (Form2 form2 = new Form2(this))
{
form2.ShowDialog();
}
}
}
Form2
public partial class Form2 : Form
{
private Form1 _mainForm1;
public Form2(Form1 mainForm1)
{
InitializeComponent();
_mainForm1 = mainForm1;
}
private void button1_Click(object sender, EventArgs e)
{
_mainForm1.UpdateMainForm( DateTime.Now.ToString());
}
}
i have 2 forms, those are form1.cs and form2.cs
on the form1, it has button1, which will call form2 to show
here's the button1 code
private void button1_Click(Object sender, EventArgs e )
{
form2 form = new form2();
form2.show(); // to call form2
this.dispose(); //to dispose form1
}
and then form2 showed, and it closed suddenly. anyone know how to solve this ?
When you close your main form with this.dispose() you are terminating the program causing form2 to be disposed also because you are diposing the reference to form2. You would be better off passing a reference to your form1 to form2 and using this.Hide() instead.
You can try something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 form = new Form2();
form.setParent(this);
form.Show();
this.Hide();
}
}
And in form2 to go back to form1
public partial class Form2 : Form
{
Form parentForm;
public Form2()
{
InitializeComponent();
}
public void setParent(Form value)
{
parentForm = value;
}
private void button1_Click(object sender, EventArgs e)
{
parentForm.Show();
this.Close();
}
}
private void button1_Click(Object sender, EventArgs e )
{
form2 form = new form2();
form2.show(); // to call form2
this.hide(); //to hide form1
}
if form1 is program starter then application will close . Hence instead
this.dispose();
U just write
this.hide();
Show() does not wait for form2 to close before continuing to the next command (dispose).
This will end up in closing form2 because it's probably running on a background thread.
Use ShowDialog to hold the execution of Dispose until the second form closes.
Also, you can set the second form to run on a foreground thread. This way the second form will not be dependent on the life of the first.
You can either use this.Hide() which should hide your current form or use a thread to open the new form.
Example: C# open a new form, and close a form...
So I want basically the user to login in first in order to use the other form. However, my dilemma is that the login box is in Form2, and the main form is Form1.
if ((struseremail.Equals(username)) && (strpasswd.Equals(password)))
{
MessageBox.Show("Logged in");
form1.Visible = true;
form1.WindowState = FormWindowState.Maximized;
}
else
{
MessageBox.Show("Wow, how did you screw this one up?");
}
However, Form1 doesn't become visible, (since I launch it as visble = false) after they log in. Can someone help?
EDIT:
Brilliant response, but my problem is still here. I basically want to load Form2 First, (which is easy I run Form1 and set it to hide) But when Form2 is closed, I want Form1 to be closed as well.
private void Form2_FormClosing(Object sender, FormClosingEventArgs e)
{
Form1 form1 = new Form1();
form1.Close();
MessageBox.Show("Closing");
}
this doesn't seem to work...
You will need to pass the reference of one form to another, so that it can be used in the other form. Here I've given an example of how two different forms can communicate with each other. This example modifies the text of a Label in one form from another form.
Download Link for Sample Project
//Your Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
//Your Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
//Added later, closing Form1 when Form2 is closed.
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
mainForm.Close();
}
}
(source: ruchitsurati.net)
(source: ruchitsurati.net)
When you log in and do Form1.visible = true; have you also tried Form1.Show(); that should show form2
However, Personally, I would prefer setting the application to run form2 directly in the program.cs file.
static void Main()
{
Application.Run(new Form2());
}
then when user successfully logs in, do
form1.Show();
this.Hide(); // this part is up to you
mind you, in form2, when / after you instantiate form1, you might want to also add this :
newform1.FormClosed += delegate(System.Object o, FormClosedEventArgs earg)
{ this.Close(); };
this closes form2 when form1 is closed
better yet do form1.Show() in a new thread, and then this.Close(); for form2. this removes the need of adding to the form2's FormClosed event: you can thus close form2 immediately after starting form1 in a new thread. But working with threads might get a little complicated.
EDIT:
form2 is form1's parent. if form2 is your main application form, closing it closes your program (generally). Thus you either want to just hide and disable form2, and close it only after form1 is closed, or start form1 in a new thread. Your edit pretty much opens form1, then immediately closes it.
I've a dgv on my main form, there is a button that opens up another form to insert some data into the datasource bounded to the dgv. I want when child form closes the dgv auto refresh. I tried to add this in child form closing event, but it doesn't refresh:
private void frmNew_FormClosing(object sender, FormClosingEventArgs e)
{
frmMain frmm = new frmMain();
frmm.itemCategoryBindingSource.EndEdit();
frmm.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
frmm.dataGridView1.Refresh();
}
However, when I add this code in a button on the parent form, it actually does the trick:
this.itemCategoryBindingSource.EndEdit();
this.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
this.dataGridView1.Refresh();
There are many ways to do this, but the following is the simpliest and it will do what you want and get you started.
Create a public method on your main form.
Modified constructor of second form to take a main form.
Create an instance of the second form passing the main form object.
When closing second form, call the public method of the main form object.
Form1
public partial class Form1 : Form {
public Form1() {
//'add a label and a buttom to form
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
Form2 oForm = new Form2(this);
oForm.Show();
}
public void PerformRefresh() {
this.label1.Text = DateTime.Now.ToLongTimeString();
}
}
Form2
public class Form2 : Form {
Form1 _owner;
public Form2(Form1 owner) {
_owner = owner;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form2_FormClosing);
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e) {
_owner.PerformRefresh();
}
}
We can also proceed this way:
We have form_1 and form_2
In form_1, create a public method. Inside this public method we put our stuff;
In form_2 we create a global form variable;
Still in form_2, pass form_1 into form_2 through form_2 constructor;
Still in form_2, make your global variable(the one we created in step 2) receive the new form_1 instance we created in form_2 constructor;
Inside the closing_event method we call the method which contains our stuff.
The method with our stuff is the method that will fill our form1 list, dataGridView, comboBox or whatever we want.
Form_1:
public fillComboBox()//Step 1. This is the method with your stuff in Form1
{
foreach(var item in collection myInfo)
{myComboBox.Items.Add(item)}
}
Form_2:
Form1 instanceForm1;//Step 2
public Form2(Form1 theTransporter)//Step 3. This the Form2 contructor.
{
InitializeComponent();
instanceForm1 = theTransporter;//Step 4
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
instanceForm1.fillComboBox();//Step 5 we call the method to execute the task updating the form1
}
I hope it helps...
You're creating a new instance of the main form which isn't effecting the actual main form instance. What you need to do is, call the code on the main form itself, just like the code you say works on the button click:
private void frmNew_FormClosing(object sender, FormClosingEventArgs e)
{
this.itemCategoryBindingSource.EndEdit();
this.itemsTableAdapter.Fill(myDatabaseDataSet.Items);
this.dataGridView1.Refresh();
}
Great answer there! The other method would have been:
Check if the form you want to update is open.
Call the method to refresh your gridVieW.
**inside your refreshMethod() in form1 make sure you set the datasource to null **
if (System.Windows.Forms.Application.OpenForms["Form1"]!=null)
{
(System.Windows.Forms.Application.OpenForms["Form1"] as Form1).refreshGridView("");
}