It's been a while since I've worked with Windows Forms applications. I have a Checkbox on the Main form and, based upon a certain condition, if the Second form needs to be opened to request additional data from the user, how should I pass (or get) back a message to the Main form from the Second form so I can tell whether or not it's okay to Check or Uncheck the Checkbox?
From what I can remember, I could use something like Pass by ref. Or is there a better way to accomplish this?
Since you are showing the child form as a dialog, and the parent form doesn't need it until the form as closed, all you need to do is add a property with a public getter and private setter to the child form, set the value in the child form whenever it's appropriate, and then read the value from the main form after the call to ShowDialog.
One way to do this would be to use an event.
In your child form, declare an event to be raised upon specific user interaction, and simply "subscribe" to this event in your main form.
When you instantiate and call you child form, you'd do like this:
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.MyEvent += frm_MyEvent;
frm.ShowDialog();
frm.MyEvent -= frm_MyEvent;
}
private void frm_MyEvent(object sender, EventArgs e)
{
textBox1.Text = "whatever"; //just for demo purposes
}
In your child form, you declare the event and raise it:
public event EventHandler MyEvent;
private void button1_Click(object sender, EventArgs e)
{
if (MyEvent!= null)
MyEvent(this, EventArgs.Empty);
}
Hope this helps
Related
I'm writing a chat application for a school project. One of the forms I have is the Contacts form, from which I open different SingleDialogue forms (they are the 1 on 1 chats). I want to make it so that when I close the Contacts form, it closes all the SingleDialogue forms I have opened.
For this I made it so that the Contacts_FormClosing event triggers the Disconnected event in my client object, and in the Contacts form I made a method:
private void On_ImDisconnected(object sender, EventArgs e)
{
foreach (SingleDialogue sd in singleChats)
sd.Close();
}
singleChats is the name of a list of SingleDialogue forms opened from the Contacts form. Every time I open another SingleDialogue, it's added to singleChats.
And in the constructor I subscribed it to the Disconnected event in the client object:
im.Disconnected += new EventHandler(On_ImDisconnected);
So far, what should happen is that when I trigger the Disconnected event in the client object On_ImDisconnected fires up and closes all the SingleDialogues, correct?
But I get an exception saying "Cross-thread operation not valid: Control 'SingleDialogue' accessed from a thread other than the thread it was created on".
Alright, then I changed On_ImDisconnected:
private void On_ImDisconnected(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(delegate
{
foreach (SingleDialogue sd in singleChats)
sd.Close();
}));
}
But now nothing happens. Can you guys help me solve this?
EDIT:
Declaration of the list:
List<SingleDialogue> singleChats = new List<SingleDialogue>();
Adding new members:
private void chatButton_Click(object sender, EventArgs e)
{
SingleDialogue sd = new SingleDialogue(im, chatTextBox.Text);
singleChats.Add(sd);
chatTextBox.Text = "";
sd.Show();
}
I'd say skip the list completely. In the constructor of your SingleDialogue Form you could add a handler to when the passed parent disconnects, and then close the SingleDialogue from within itself.
So if I had to guess what the constructor looks like, you could do something like this:
public SingleDialogue(<someFormType> im, string stringThingy)
{
...some initialization code...
im.Disconnected += new EventHandler(im_Disconnected); //Subscribe to the parent's Disconnected event.
}
private void im_Disconnected(object sender, EventArgs e) //When the parent disconnects.
{
if(this.InvokeRequired) { this.Invoke(() => this.Close()); }
else { this.Close(); }
}
Note that I'm not a native C# developer, so if I did something wrong please tell me. :)
As I understood the scenario, you're keeping a list of forms in Contact form and want to close it.
I suppose your approach is wrong, when you're subscribing every form to the Disconnected event. Why not close the form on event trigger from inside of it?
You just need this code in your every SingleDialogue instance:
//subscribe to event handler, most probably in constructor
im.Disconnected += new EventHandler(On_ImDisconnected);
//close on event fire
private void On_ImDisconnected(object sender, EventArgs e)
{
this.Close();
}
You don't need to go through the list and close the forms from a parent form.
If I got the question wrong, please correct me.
I want to close two forms at the same time. I have one main form that starts with program. when user click button, the main form will hide and other form will pop up. on the second form if user click "back to main " button, it should hide second form and show main form. But the problem is if user tries to close the second form it should close the main form as well. How can i close the main form as well
I would just use the Application.Exit() for what is requested by this thread.
Application.Exit();
UPDATE: corrected
I had said this will not call the form closing events but in documentation it does actually call it here is a link to the documentation
http://msdn.microsoft.com/en-us/library/ms157894(v=vs.110).aspx
It was better if you specified what codes you wrote for going back to main form, so I could help you by changing your codes. But now because I don't know how you did it, I have to write codes for both of those tasks.
It can be possible using a Boolean variable to do what you want. Follow bellow codes:
public partial class MainForm : Form
{
//"Click" event of the button that should opens the second form:
private void goToSecondForm_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(); //Or you can write it out of this method.
this.Hide(); //Hides the main form.
f2.ShowDialog(); // Shows the second form.
this.Show(); // Shows the main form again, after closing the second form using your own button.
}
}
public partial class Form2 : Form
{
bool selfClose = false; //False shows that user closed the second form by default button and true shows that user closed it by your own button.
//"Click" event of the button that should closes just the second form and returns user to the main form:
private void ownCloseButton_Click(object sender, EventArgs e)
{
selfClose = true; //Means user clicked on your own button.
this.Close(); //So the program closes the second form and runs f2_FormClosed method, but because selfClose became true here, happened nothing there and program will go back to goToSecondForm_Click method in the main form and will run this.Show() .
}
//"FormClosed" event of the second form :
//Whether user clicked on your own button or on the default one, this method will run.
private void f2_FormClosed(object sender, FormClosedEventArgs e)
{
if (!selfClose) //It means user didn't click on your own button and both of forms must be closed .
Application.Exit(); //So the program closes all of forms (actually closes the program) and couldn't access to any other commands (including this.Show() in goToSecondForm_Click method).
}
}
As others have said, you need to somehow call .Close() on the main form when your child form is closed. However, as you've pointed out, you don't have a reference to the main form automatically in your child form! That leaves you with a few options.
1. Exit the application immediately.
This is done by calling Application.Exit(); in your child form's "back to main" button's click event handler. It will immediately close all forms, which might simply be what you want.
// .. ChildForm code ..
void OnBackToMainClicked(object sender, EventArgs e)
{
Application.Exit();
}
2. Pass a reference to the main form to the child form.
This is probably the most common way to solve this problem in general. When you create your child form in your main form, you'll need to pass a reference as follows:
// .. MainForm code ..
void OnGoToChildForm(object sender, EventArgs e)
{
var childForm = new ChildForm(this);
childForm.Show();
}
// .. ChildForm code ..
private MainForm mainForm; // This is where the child form will keep a reference to
// the main form that you can use later
public ChildForm(MainForm mainForm)
{
// This is the child form's constructor that we called above,
// and it's where we'll save the reference to the main form
this.mainForm = mainForm;
}
// This also needs to be the event handler for the close event
void OnBackToMainClicked(object sender, EventArgs e)
{
this.Close();
mainForm.Close();
}
3. Add an event handler on the child form's FormClosed event. This is a safe way to solve the problem if you are concerned about keeping your main application logic under the control of the main form. It's similar to the solution suggested by Lamloumi above, but it's all done in the main form's code.
// .. MainForm code ..
void OnGoToChildForm(object sender, EventArgs e)
{
var childForm = new ChildForm(this);
childForm.FormClosed += new FormClosedEventHandler(SecondForm_FormClosed);
childForm.Show();
}
void SecondForm_FormClosed(object sender, EventArgs e)
{
// Perform any final cleanup logic here.
this.Close();
}
Form1 _FirstForm = New Form1();
Form2 _SecondForm = New Form2();
MainForm _MainForm = new MainForm();
_FirstForm.Close();
_SecondForm.Close();
_MainForm.Show();
Normally , in the Home form you have some ting like this :
SecondForm second= new SecondForm ();
second.Show();
this.Hide();
In the SecondForm you must ovveride the event of closure like this :
public class SecondForm :Form{
public SecondForm()
{
InitializeComponent();
this.FormClosed += new FormClosedEventHandler(SecondForm_FormClosed);
}
void SecondForm_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
}
To be sure that your application is closed after you close the form. because the Home from is still active and hidden if you don't.
use this in Form2
private void button1_Click(object sender, EventArgs e)
{
Form1.FromHandle(this.Handle);
}
There Handle are the same now ;
hope this work.
I have a C# application in which I need specific or a function to execute on a form after closing the active form.
The form in which I need the code to excute becomes the active form after the previous active form is closed. So in a nutshell after closing this form the form in which I need the event handler or function to run will then become the active form. Is there a way that this is possible?
I have tried the Form_Enter event handler on the form that becomes active after the other form is closed, but that did not work.
I believe you can achieve what you are trying to do more simply. The code you use to show Form2 from Form1 (Main), you can add your code there like so:
Class Form1 {
private void button_click(object sender, EventArgs e) {
Form2 newForm = Form2();
newForm.ShowDialog(); // To prevent the main form carry on
// Your code needed to be excuted
}
}
In the form closing event set the DialogResult as follows:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.DialogResult = System.Windows.Forms.DialogResult.Yes;
}
When you open the form look for the response as follows:
if (Form1.ShowDialog() == DialogResult.Yes)
{
////do stuff.
}
I hope this helps.
I have a Main page that contains a listBox.
When a user selects a profile form the list box, this opens up a child window called pWindow.
This window as the option to delete the current profile via a hyperlink button that opens up a another confirmation window called dprofile.
My question being is it possible that once a user has confirmed to delete the current profile they are in, and confirmed it in the button click on dProfile, how can I update the listBox in the first Main page so that the list no longer contains the deleted profile (which it is not doing at present.
In the dProfile window I have created an event -
public event EventHandler SubmitClicked;
Where in the OK button click I have-
private void OKButton_Click(object sender, RoutedEventArgs e)
{
if (SubmitClicked != null)
{
SubmitClicked(this, new EventArgs());
}
}
So on the Main page I have added-
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
WebService.Service1SoapClient client = new WebService.Service1SoapClient();
listBox1.Items.Clear();
client.profileListCompleted += new EventHandler<profileListCompletedEventArgs>(client_profileListCompleted);
client.profileListAsync(ID);
}
I thought this may have updated the listBox as it was confirmed in the dProfile form however when the form closes, the listBox stays the same and I have to manually refresh the webpage to see the update. How can I do this?
If I understood it correctly then you have three pages. Main, pWindow and dProfile. Earlier you were trying to close pWindwow from dProfile and that was working properly. Now you want to refresh the listBox1 on Main Page.
To achieve that you may follow a similar strategy. You are probably opening pWindow from Main page with something on the following line
pWindow pWin = new pWindow();
pWin.Show();
Now you may define a new event in pWindow class.
public event EventHandler pWindowRefeshListBox;
Then in your event handler for deleteProfile_SubmitClicked you may raise the event to refresh listbox1, something on the following line:
private void deleteProfile_SubmitClicked(object sender, EventArgs e)
{
if(pWindowRefreshListBox != null)
pWindowRefreshListBox(this, new EventArgs());
this.Close();
}
Then in your main page register the event against pWin object, which you defined earlier.
pWin.pWindowRefreshListBox += new new EventHandler(pWindow_pWindowRefreshListBox);
Then define the event in Main page.
private void pWindow_pWindowRefreshListBox(object sender, EventArgs e)
{
listBox1.Items.Clear();
}
This should refresh the listbox. I haven't test the code or the syntax. So you may check it
before implementing.
EDIT
you may define the event in dProfile as static
public static event EventHandler SubmitClicked;
Then you will be able to register it in Main and pWindow against Class Name
dProfile.SubmitClicked += new ..............
Then implement it accordingly, in pWindow, close the window and in main refresh listbox
EDIT:
You may create instance of deleteProfile on the main page register the following in your main
deleteProfile.SubmitClicked += new EventHandler(deleteProfile _SubmitClicked)
this should work
How can I get my windows form to do something when it is closed.
Handle the FormClosed event.
To do that, go to the Events tab in the Properties window and double-click the FormClosed event to add a handler for it.
You can then put your code in the generated MyForm_FormClosed handler.
You can also so this by overriding the OnFormClosed method; to do that, type override onformcl in the code window and OnFormClosed from IntelliSense.
If you want to be able to prevent the form from closing, handle the FormClosing event instead, and set e.Cancel to true.
Or another alternative is to override the OnFormClosed() or OnFormClosing() methods from System.Windows.Forms.Form.
Whether you should use this method depends on the context of the problem, and is more usable when the form will be sub classed several times and they all need to perform the same code.
Events are more useful for one or two instances if you're doing the same thing.
public class FormClass : Form
{
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
// Code
}
}
WinForms has two events that you may want to look at.
The first, the FormClosing event, happens before the form is actually closed. In this event, you can still access any controls and variables in the form's class. You can also cancel the form close by setting e.Cancel = true; (where e is a System.Windows.Forms.FormClosingEventArgs sent as the second argument to FormClosing).
The second, the FormClosed event, happens after the form is closed. At this point, you can't access any controls that the form had, although you can still do cleanup on variables (such as Closing managed resources).
Add an Event Handler to the FormClosed event for your Form.
public class Form1
{
public Form1()
{
this.FormClosed += MyClosedHandler;
}
protected void MyClosedHandler(object sender, EventArgs e)
{
// Handle the Event here.
}
}
public FormName()
{
InitializeComponent();
this.FormClosed += FormName_FormClosed;
}
private void FormName_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
{
//close logic here
}
Syntax :
form_name.ActiveForm.Close();
Example:
{
Form1.ActiveForm.close();
}