I have a refresh button on my user control that works just fine every time I click on it. This is the code to its click event:
private void btnRefresh_Click(object sender, EventArgs e)
{
if (!RefreshFolder())
{
Notify(new string[] { "Refresh failed." });
}
else
{
Notify(new string[] { "Refreshed." });
}
}
Notify function happens to be a delegate call from my main form. This function works well when called normally. What I want to do is to raise the above event when my user control is loaded. But when I call btnRefresh.PerformClick() on the load event the application does not start and quits automatically after a short while. But when instead of the Notify function I put a MessageBox.Show("blah") the function works properly.
This is the delegate I use:
public delegate void NotifyMe(string[] messages);
And on my main form I have the following line in its constructor so that my user control can use the Notify function of the main control:
userctrlSelectManualCampaignFile.Notify += new NotifyMe(Notify);
The function works perfectly well as I said unless when I try to raise the click event. Any ideas?
Update:
Main form constructor:
public MainForm()
{
InitializeComponent();
logger = new Logger();
connectionHelper = new ConnectionHelper();
datetimeHelper = new DateTimeHelper();
userctrlSettingsGeneral.Notify += new NotifyMe(Notify);
userctrlSelectManualCampaignFile.Notify += new NotifyMe(Notify);
}
My user control constructor:
public ManualCampaignFiles()
{
InitializeComponent();
}
You're probably causing a "silent" exception to be thrown, causing your application to quit.
Such exceptions can be "swallowed" by the framework, for example within event handlers.
Try setting your debug environment to break on thrown exceptions. For this, go to the Debug > Exceptions... menu, then in the dialog that shows up, make sure to check the "Thrown" checkbox corresponding to Common Language Runtime Exceptions.
This way, when you lauch your program, it will break at the moment an exception is thrown, allowing you to figure out what is going on.
Cheers
I found the answer in another forum:
Before event raising you should check if event is not null. This is
common pattern for event raising.
Answer provided by Vitaliy Liptchinsky.
But Hans Passant's answer was also very close to truth.
Related
I want to prevent a button click from queuing. In testing I have a Form, a Button and in the Code-Behind I have the event handler:
private void button1_Click(object sender, EventArgs e)
{
if (_codeRunning)
return;
_codeRunning = true;
//Application.DoEvents();
//button1.Enabled = false;
_click ++;
Debug.WriteLine("Click Number: " + _click);
Task.Delay(5000).Wait();
//button1.Enabled = true;
_codeRunning = false;
}
When I run debug and click the button twice or three or four times rapidly, Debug Output shows each click about five seconds after the last one. What I would like it to show is a single Click and drop the rest until first Event is complete.
I have also tried to disable the button, as well as temporarily remove the Handler from the Button_click event. It is all the same results.
There are various amounts of trouble you'll get into when you hang-up the UI thread like this. This is certainly one of them, nothing pleasant happens when the user wildly bangs on the button to try to get something noticeable to happen. And sure, those clicks won't get lost, they stay stored in the message queue. To activate your Click event handler again when your event handler stops running.
Pretty important to learn how to use the BackgroundWorker or Task classes to avoid this kind of trouble. Just setting the button's Enabled property is then enough to solve this problem.
Purging the mouse clicks from the message queue is technically possible. But ugly to do, it requires pinvoke. I'll hesitantly post the alternative, don't assume that this is in general a good strategy. You'll need to read this post to have some insight into why DoEvents() is a dangerous method.
private void button1_Click(object sender, EventArgs e) {
button1.Enabled = false;
button1.Update();
'' long running code
''...
Application.DoEvents();
if (!button1.IsDisposed) button1.Enabled = true;
}
The Update() call ensures that the user gets the feedback he needs to know that banging the button repeatedly isn't going to do anything useful. The DoEvents() call will dispatch all the queued-up mouse clicks, nothing happens with them since the button is still disabled. The IsDisposed test is essential to solve the problem with DoEvents(), it ensures your program won't crash when the user clicked the window's Close button while the code was running.
Use the HourGlass class in this post to provide more feedback.
I had a button that on click event was going to run a method. Same issue happent and when the user clicked multiple times the method was triggered multiple times. So I made a boolean and changed it value when the method started.
private bool IsTaskRunning = false;
private void MyMethod()
{
if ( IsTaskRunning==false )
{
IsTaskRunning=true;
// My heavy duty code that takes a long time
IsTaskRunning=false; // When method is finished
}
}
So now the method runs only if it's done the last time.
So I've been following the Visual Studio tutorials that microsoft has available (more specifically the math quiz one found at https://msdn.microsoft.com/en-us/library/vstudio/dd492172.asp)
but I deviated a bit from the tutorial because I wanted to see if I could create an event and call it using the EventHandler delegate though it might not be the best solution.
public event EventHAndler quizStarted;
here is the code for creating the event.
now in the method
public Form1()
{
this.quizStarted += new System.EventHandler(this.showThatTheQuizStarted);
InitializeComponent();
}
I have initialized my event with an instance of the EventHanlder that points to my showThatTheQuizStarted method.
public void showThatTheQuizStarted(object sender, EventArgs e)
{
MessageBox.Show("Quiz Has Started");
}
and finally when the start button is pressed I call the quizStarted event as shown below.
private void startButton_Click(object sender, EventArgs e)
{
startButton.Enabled = false;
quizStarted(this, new EventArgs());
this.StartTheQuiz();
}
in this order the message box goes away after hitting okay once, also in StartTheQuiz() nothing calles a message box directly or indirectly.
but if I place the this.quizStarted += new System.EventHandler(this.showThatTheQuizStarted); line into the startButton_Click method, the message box appears twice one right after the other.
Though I found a solution I would like to know why this happens if I place this line of code out of the constructor.
If...
this.quizStarted += new System.EventHandler(this.showThatTheQuizStarted);
... gets called multiple times, as would happen if you move it inside a button Click event handler method, then you are in fact adding and registering a new event handler every time.
In other words, when quizStarted is invoked, it may call multiple event handlers, depending on how many you choose to register. If you register the same event handler multiple times, then it will get called as many times.
That's why you want to leave the registration in a place where you are guaranteed to register the event handler once and only once.
The MainForm_Load doesn't work, the form is showing as I designed, but nothing in the load method happens. When I put a breakpoint it just skip on this method, I tried to delete the method and recreate it but it still not working.
I'm using Visual Studio 2010, everithing works fine with other projects I did.
Even the most basic function not working in it.
Here is an example:
public FormMain()
{
InitializeComponent();
}
private void FormMain_Load(object sender, EventArgs e)
{
MessageBox.Show("Test");
}
Any ideas??
Tnx
Did you type this by hand?
You need to assign the event, if you do this on the designer it will auto generate the code. If you want to do by hand you have to manually assign the event.
public FormMain()
{
InitializeComponent();
this.Load += FormMain_Load;
}
Everything looks fine here.Please check this.
Go to Properties window of your form(here it is FormMain.cs[Design] ). Click on event section. check in Load event your
FormMain_Load
method is defined or not ?
give the breakpoint and check it is calling or not.
Give breakpoint on the form constructor .
And you need to check, From where you are calling this form ?
if this form is the first form in your application, then go to Program.cs file. and check there this is available or not inside Main Function.
Application.Run(new FormMain());
In FormMain.Designer.cs page check
this.Load += new System.EventHandler(this.FormMain_Load);
is available inside
private void InitializeComponent()
{
}
or not?
I have a working method
something_Click(object sender, EventArgs e)
{
code
}
...
It of course executes after someone clicks the element. What I need to do is, to execute this method immediately after the element appears on the screen (it is StripStatusLabel). I have tried just to add a call of the method to beginning of the code, but it did nothing.
You can call Button.PerformClick on your button in a Form.Load event handler.
You might also want to consider moving that logic into its own method, and call that method from both the button handler and the Load event, as this will be more clear. (It's obviously code you want triggered on more than just a "button click").
Depending on what framework you are targeting (WPF vs Winforms) you might be able to handle the Load event instead. It triggers when the element appears on screen.
It's not best practice to fire a form event which would normally be originated from teh user. In the sense, you are trying to "fake" the click. Think of the future debugging, or of the colleague who might inherit your project. When inspecting code you would expect something_Click to only be fired when there is a click on "something".
A better solution is to put the "code" part in your snip into a method whose name reflects what it really does.
They you may fire this method in different areas. Fire it at the click, at the load, anywhere.
something_Click(object sender, EventArgs e)
{
DoStuff();
}
OnAppearToScreen()
{
DoStuff();
}
DoStuff()
{
//code that actually does stuff
}
Later on, when you want to check when "the stuff" was done to your object, you can easily tell by code inspection.
Let's say I have a form SomeForm that inherits from Form.
public class SomeForm : Form
{
private void SomeForm_FormClosed(object sender, FormClosedEventArgs e)
{
MessageBox.Show("FormClosed event in SomeForm class");
}
}
public class Consumer
{
SomeForm someForm = new SomeForm();
someForm = null; //Ideally the messagebox would display here
SomeForm someForm = new SomeForm();
someForm.Close(); //Messagebox would display in this case as well
}
I want to show that MessageBox whenever the form is closed. Should I stick that in the FormClosed event? Is it safe to assume that the FormClosed event will fire every time something like the destructor is run? Is there a better place to put this code that must occur when the form is closed?
EDIT
Someone made a good point in the comments below. It seems the event does not fire when the instance of the class is set to null. However, will the destructor or some other method still be called when the instance is set to null. I want to guarantee that my code runs when the user is finished with the class.
I'm also aware that forcibly shutting down the system, ending the process, acts of God, etc will not cause my code to run no matter what. =)
Yes, it will be called unless something exceptionably happens, like killing it via system commands or pulling the plug. Other cases include
setting the variable to null (not calling the Close method)
Exception in another delegate: All events are MulticastDelegates, and the delegates are executed in order of appearence in that MulticastDelegate, if one of the previous delegates before yours causes an exception, your delegate will not be called.
It will get called unless your executable is forcibly closed (via task manager or taskkill from the command line) or the program crashes.
EDIT: I did some experimentation and found the following:
If you set your reference to the form to null, the form remains visible, and when the form is closed, the event gets raised.
If your form is a child form and the main form gets closed, the child form closes WITHOUT the event being raised.
If you call the form's Hide() method, the event does NOT get raised. Subsequently closing the main form, as mentioned above, will not cause the event to get raised.
Overriding OnClosed() will not help because it's still not called if the main form is closed.
Calling the form's Dispose() method (which is what the GC would eventually do if nothings pointing at it) will also not cause the event to get raised.
It looks like there really isn't a way to GUARANTEE the code will get called from within the form. You can put the code after the Application.Run(); in your Main() and it will get called there. There's also an event for Application.ApplicationExit that would get called unless you have exceptional circumstances (forcibly closed or crash).
You can register a handler for the Application.ApplicationExit event in your form, but be aware that by this time, your object has already been disposed, so you can't do anything with it.
FormClosed event is raised by OnClosed method. So if you want certain level of guarantee, you can override OnClosed method.