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();
}
Related
I want to have a return value from my WPF window without close it.
I have an DLL with WPF usercontrol inside, I call it from my DLL code.
I have to call it, it returns me datas, then I send it datas.
But I don't want to create two different instance of the same window.
My code :
MP.UserControl1 a = new MP.UserControl1();
a.ShowDialog();
if (a.DialogResult.HasValue && a.DialogResult.Value == true)
{
a.Hide();
InitialDatas = a.inputData;
}
else
return 0;
Then I elaborate InitialDatas
And now I want to call a method inside my "a", and show it again, without create a new window.
Code :
a.SetValue(result, off1, InitialDatas);
a.ShowDialog();
I got error message : Cannot set visibility or call Show, ShowDialog or EnsureHandle after a window has been closed
Is it possible to solve?
I would solve this with an event model. You could do the following:
Create an event in the Form
Create an event handler in the caller
Subscribe to the event and do your logic
The called form:
namespace MyApplication
{
public delegate void MyEventHandler(object source, EventArgs e);
public class MyForm : Form
{
public event MyEventHandler OnInitialData;
private void btnOk_Click(object sender, EventArgs e)
{
OnInitialData?.Invoke(this, null);
}
}
}
In your other Form:
MP.UserControl1 a = new MP.UserControl1();
a.OnInitialData += UCA_OnInitialData;
private void UCA_OnInitialData(object sender, EventArgs e)
{
MP.UserControl1 a = sender as MP.UserControl1;
a.SetValue(result, off1, a.inputData);
}
a.ShowDialog();
As the error message states, you cannot close the window and then open it again.
Instead of closing a window you could hide it by calling the Hide() method and then showing it again by calling the Show() method.
But since the ShowDialog() method doesn't return until the window has been closed, this won't work for a dialog window though. If you require a modal window, you will have to create a new instance of the window and open this one. This shouldn't really be an issue though.
So I guess the answer to your question is simply no. You cannot re-open a closed dialog window.
I have many custom controls on my main form that utilize an event to signify they have done processing. They all share this same event (~100 controls or so).
The main form consumes this event but I do not have a clue how to find an efficient way at getting to the one that raised the event without having really inefficient code.
My controls are contained within a List<T> called controlList and are hosted on their own project.
My event looks like so:
public void OnTaskComplete(object sender, custom_control_project.TaskCompleteEventArgs e)
{
foreach (var control in controlList)
{
if (control.Visible) // <--- THIS IS WRONG! WHAT COULD THIS BE???
{
try
{
...// LOTS OF PROCESSING!
}
catch
{
...
}
finally
{
...
}
}
}
}
If I want to use less controls, I make them invisible and disabled, hence the control.Visible.
How can I make it so I only do work on the one control that raised the event without having to process so much unneeded iterations?
The sender parameter is the object that raised the event. You can cast this to a control.
Assuming the all of the controls are wired to the same event (which you indicate):
protected void Button1_Click(object sender, EventArgs e)
{
((Button)sender).Visible = true;
// or more generally:
((WebControl)sender).Visible = true;
}
You will need to cast the sender to a common, base type. If you go with a base type, WebControl will allow you to access the Enabled property while Control will not.
I wrote a small control that creates a popup for my Win8 Phone application which does all the nasty things for me like rotation, proper placement etc.
The popup is opened in a Popup control but not on a new phone page.
To close the popup, my control hooks up to the "backKeyPressed" event of the underlying page.
This works like charm until the underlying page has its own implementation of BackKeyPressed event. In this case, the page event is triggered but not the popup control event.
If I would own the event, I could create my own stack to call the last added event first, but I do not own the event of the pages.
As far as I know, I am unable to unregister any previously attached event handler and reassign it once my control unsubscribes from the event.
I could have only one implementation for the BackKeyPressed event which then informs the popup control to close itself (if open), if nothing was open, do the Page specific implementation. But this would require code changes on all pages where I might want to use the popup. Even worse, if I have 5 possible popups, I would have to check all of them :-(
So I am looking for an option to handle this centrally.
What other options do I have to overcome this situation?
Normally you cannot change the order of fired events - they are executed in registered order, but it's not required by specifications - source.
But as Jon Skeet says here:
Summary: For all sane events, you can rely on the ordering. In theory, events can do what they like, but I've never seen an event which doesn't maintain the appropriate ordering.
it is fired in registered order and should be.
BUT for your purpose (I think) you can set an event to invoke your method where you would control the order. I think simple example can show this behaviour:
public partial class MainPage : PhoneApplicationPage
{
private List<EventHandler<CancelEventArgs>> listOfHandlers = new List<EventHandler<CancelEventArgs>>();
private void InvokingMethod(object sender, CancelEventArgs e)
{
for (int i = 0; i < listOfHandlers.Count; i++)
listOfHandlers[i](sender, e);
}
public event EventHandler<CancelEventArgs> myBackKeyEvent
{
add { listOfHandlers.Add(value); }
remove { listOfHandlers.Remove(value); }
}
public void AddToTop(EventHandler<CancelEventArgs> eventToAdd)
{
listOfHandlers.Insert(0, eventToAdd);
}
public MainPage()
{
InitializeComponent();
this.BackKeyPress += InvokingMethod;
myBackKeyEvent += (s, e) => { MessageBox.Show("Added first"); e.Cancel = true; };
AddToTop((s, e) => { MessageBox.Show("Added later"); });
}
}
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
If I have a button which does something and also a double-click event on a data grid which I want to do the same thing, what is the best way to ensure that only one function has to be maintained?
Apart from doing the following, is there any fancy C# way to indicate that two events are to do the same thing?
void button1_Click(...) { MyFunction(); }
void dataGrid1_DoubleClick(...) { MyFunction(); }
void MyFunction() { // do stuff }
I suppose that you are talking about a DataGridView (WinForms) so the signature of the event DoubleClick in the DataGridView and the signature of Click event on a button control is the same.
(An EventHadler). In this case you can simply set the same method using the form designer or manually bind the event
dataGridView1.DoubleClick += new EventHandler(MyFunction);
button1.Click += new EventHandler(MyFunction);
Of course the MyFunction method should match the expected signature of an EventHandler
private void MyFunction(object sender, EventArgs e)
{
// do your work
}
Reviewing my answer after a few minutes I wish to add:
If you find yourself in a situation in which you need to differentiate between the controls using the sender object (like Control c = sender as Control; if (c.Name == "someName") ) I really suggest you to return to the first idea. Call a common method but keep the EventHandler separated for each control involved.
Using VS, in the form's designer view You can set the procedure You want to call to each control's each event in the control's properties window.
image
Just to add to what Steve said, you will want to bind these events to your function manually in the Load event of your form, instead of using the events under the lightning bolt in the properties window in the designer, like so:
private void Form1_Load(object sender, EventArgs e)
{
button1.Click += MyMethod;
dataGridView1.DoubleClick += MyMethod;
}
void MyMethod(object sender, EventArgs e)
{
//Do Stuff
}
Also, declaring a new instance of the EventHandler class has been redundant since Anonymous methods were introduced to C#, you can just point the event directly at the method as shown above.