I have a button with an event handler attached to it; 2-clicking it in the designer takes me to the code. Nowhere is the handler being unhooked/detached.
Some code I expected to run apparently isn't, so I put a bunch of MessageBox.Show()s in the handler, even at the very beginning, but none of them display (Note: I can't step through the code; I have to do it this way (arggghhhh)).
Here's some of the code:
private void btnFind_Click(object sender, System.EventArgs e) // Find and list Records
{
MessageBox.Show("Made it into btnFind_Click 0"); //TODO: Remove after debugging
try
{
if (barcodeScanner != null)
{
// Turn off the listening
barcodeScanner.BarcodeScan -= new BarcodeScanner.BarcodeScanEventHandler(barcodeScanner_BarcodeScan);
}
MessageBox.Show("Made it into btnFind_Click 1"); //TODO: Remove after debugging . . .
What could be preventing this code from being executed?
UPDATE
Based on Mike C's idea, I added a MessageBox to the button_close handler. And when I click it, it does fire, but only after other code runs first; in this case, that other code doesn't prevent the Close_Click from (eventually) firing; with the Find button, though, it completely preempts it...IOW, I see the message from the Close button at the end when I click it, but I never see any of the messages in the Find button handler when I click it...
UPDATE 2
Oh my lanta/say it ain't so, Joe! What's happening is an event is being kicked off in the form's overloaded constructor, and somehow this event is always fired just then (after clicking the find button). The message I'm seeing, that preempts everything in the button event handler, takes place in a method which is called by processBarcode() which is called by processBarcode1(), which is invoked from barcodeScanner_BarcodeScan1(), which is called by barcodeScanner_BarcodeScan(), which is set up in frmEntry's overloaded constructor. If the previous coder had intended to drive me insane, he couldn't have done much better.
I guess there's a reason there's so much maintenance work "out there" or "out here": because there's so much bad broken code AND because the cats who make such a mess scratch a bunch of sand on it and walk away.
And this code is chock full of "huh?!?##$%^?!?" moments, where bizarre gyrations are not commented on at all, and yet there is this comment:
// Check connection
checkConnection();
The problem could be that the Click event of the button is not subscribed to properly. If there is no line resembling
this.btnFind.Click += new System.EventHandler(this.btnFind_Click);
in the Designer file of the form, that's it.
Related
I am working with some legacy code that uses a lot of events. Basically, every method is called throught an event. All those events have only one subscriber.
When reading some code that raises an event, how can I quickly navigate to the code of this one subscriber?
e.g I am reading trough some code:
event xy DoStuff_Event;
void foo()
{
DoStuff_Event()
}
Now I want to know what code would be executed here.
So I click on DoStuff_Event()->"Find all references"
Then I search the references for the line DoStuff_Event += DoStuff_ForReal()
(There is always only one such line in this codebase)
Then I click on DoStuff_ForReal()->"Go to definition"
Now I finally can read the code that will be executed when DoStuff_Event() is called. Usually this code will consist of several further event calls, which in turn call even more events, so I repeat the whole process.
Is there a faster way to jump from the line DoStuff_Event() to the method definition of DoStuff_ForReal()?
For my case, when there is always only one subscriber for each event, it seems like this search could be automated.
I am implementing Custom Task Panes with E-Mail Messages in Outlook.
The core is taken from this link MSDN (Walkthrough: Displaying Custom Task Panes with E-Mail Messages in Outlook)
Handler for property change is added:
void TaskPane_VisibleChanged(object sender, EventArgs e)
{
Globals.Ribbons[inspector].ManageTaskPaneRibbon
.toggleButton1.Checked = taskPane.Visible;
...some code here...
mailItem.PropertyChange += PropertyChangeHandler;
}
PropertyChangeHandler checks is recipients have changed and does some heavy routine with posts and so on. But... If I add 10 recipients and start to remove them with backspace PropertyChangeHandler stops firing at some point.
No errors. Buttons on custom task pane work fine.
What is wrong?
Seems that either event is eaten or inspector is incorrect, but I cannot spot problem and find the solution.
I also think that it might be about "heavy load" when next event is fired before previous is completed, but this is a guess
You need to call the Save method or save the message explicitly to make the PropertyChange event fired. Outlook caches values in the UI and doesn't propagate changes until the item is saved.
Also I'd suggest creating a log file (a regular text file) where you can write the debug statements. Thus, you will understand what happens in the code.
I have a class which performs an async operation.
While that async operation (which works downloads a file) it should show a new dialog.
To close that dialog again and also show a progress in it, I made events that are fired and should let the event handlers do actions.
To show you that a bit clearer:
var dialog = new DownloadDialog();
DoAsyncDownload();
if (dialog.ShowDialog() == DialogResult.OK)
{
dialog.Close();
// Go on
}
So the download dialog is just there to show the user that a download is going on.
In order to show a progress and close the dialog then again, I want to work event-based.
What I made is an event:
public event EventHandler<EventArgs> DownloadFinished();
protected virtual void OnDownloadFinished(Object sender, EventArgs e)
{
if (DownloadFinished != null) DownloadFinished(sender, e);
}
Well, so in the method that is called async I call it like that, when the file is downloaded:
OnDownloadFinished();
Then this event is fired.
So, in order to make the dialog receieve this event I set an handler with the correct signature in the dialog's class.
Then I set this handler like that:
this.DownloadFinished += new EventHandler<EventArgs>(dialog.DownloadFinishedHandler);
But the event handler does never execute its code. :(
I checked this with breakpoints.
I think the problem is using a webclient to download the file. Its eventhandlers are not set at the right time I think.
The webclient is declared as a member outside any functions or anything, so that every function can access it.
Then the code in the method that is called async looks like that:
packageDownloader.DownloadFile(MyUrl, "Url");
OnPackageDownloadFinished(this, EventArgs.Empty);
Like I already said above, this functions is called then.
The same problem is appearing with the progress changed, it is the same.
The thing I am sure that there is any way this would work or the webclient is the guilty guy, is that I have already done the same thing with another method and there the eventhandlers are called and everything works fine. So in this other method another thing is done, but after that it also raises an event. And the handler set is exactly the same.
Only here it doesn't work, I think it is the webclient.
PS: If you have any questions or something isn't clear to you, ask me. ;)
The problem was very dumb. I didn't download the file asnyc, so no events could be raised that clear way.
If I have a project and I do not how design corresponds to the code is there a way to make the debugger break every time I press any button so I can quickly navigate to the right place in the code or am I asking for too much here?
You can make a call to System.Diagnostics.Debugger.Break() to tell any attached debuggers to break at that line.
If none are attached, Windows will try to launch any registered debuggers. If not are registered, you'll get an exception/crash of the application. So, don't leave it in the code in production :)
e.g. (as per icemanind's comment)
#if DEBUG
Debugger.Break();
#endif
If you want to break on a click of any button, it gets a bit tricky. The easiest thing is to write a Button wrapper class and override OnClick and put your Break call in there. For example:
public class ButtonWedge : Button
{
protected override void OnClick(System.EventArgs e)
{
Debugger.Break();
base.OnClick(e);
}
}
Once you add that class you can drag and drop it on the design surface. But, if you've already got code, you can edit the designer.cs file and replace System.Windows.Forms.Button with ButtonWedge.
Once in OnClick, you can see where the Click event will go by looking at the base classes Events array with the Control.EventClick key. That will contain a multicast delegate that you can look at the Method and Target properties to find out what has subscribed to this Click event. In other words, the name of the click handler at runtime will be:
string handlerName = base.Events[Control.EventClick].Target.GetType().FullName + '.'
+ base.Events[Control.EventClick].Method.Name;
It doesn't really put a break point in a particular Click event but lets you know what's going on and where...
If you meant a button on the program in the project then use Peter's answer. If you were asking can you make a button on the keyboard or mouse cause execution to break or pause, you can press Ctrl+Alt+Pause.
Why you cannot just DoubleClick on the button in design mode. Its open in code right on the function that handles a click event.
In VS2008, if I double click on the event handler VS creates a default event handler with a default name, e.g. combobox1_SelectedIndexChanged.
Say, for example, i now rename combobox1 to cbStatus. It still has the same event handler, so i now change that to cbStatus_SelectedIndexChanged.
Is there a way, where VS can change the initial combobox1_SelectedIndexChange to cbStatus_SelectedIndexChange rather than generate a new cbStatus event handler in addition to the old event handler? Because every time i have to cut and paste the code to the new event handler and then delete the old one.
In addition, if i have defined the initial event handler and then no longer require the handler, i cannot simply delete the handler from code, as the form designer then complains that it cant find the original event handler. Is there a way where VS can automatically remove the assignment of the event handler from the form designer?
I seem to be spending all day cutting and pasting, and deleting event handler assignments from the forms designer code.
When you rename the control, you should rename the event handler too. The proper way to do this is by refactoring the code.
To do this, just right-click the name of the event handler in the Visual Studio code editor and choose Refactor -> Rename... That will allow you to automatically change the name of it everywhere it's used.
In the case of an event handler, it's probably only used in one other place (the point in code where it's added to the event), so it's not too much trouble to change it manually. You can apply this technique to pretty much anything, though, making it extremely useful when something you're changing is referred to from several different places.
You just have to find the place in the generated code where the combobox1_SelectedIndexChange method is declare and change the name to cbStatus_SelectedIndexChange.
After you change the method name, you also have to update the line where you register the handler:
cbStatus.SelectedIndexChange += new
SelectedIndexChangeEventHandler(cbStatus_SelectedIndexChange);
Just type the new name, then recompile. By this I mean - Change
protected void combobox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
to
protected void renamedcombobox_SelectedIndexChanged(object sender, EventArgs e)
{
}
and then recompile
Visual Studio will throw a compile-time error, because the method that is expected is no longer there.
Double-click on the error in the Output window to go to the assignment of the error handler, and change the error handler there to match the new function name.
Edit - added
The above step will jump you to the line of code described in Justin's answer...
End Edit
I know that's clear as mud, but try it and you'll figure it out with little or no difficulty.
If you single-click instead of double-clicking to automatically create the event handler, you can specify the handler name you want. You could make it something like "SelectedStatusChangedHandler", which is independent of the combobox's variable name. Then press 'enter' and let VS create the handler for you.