Lets say we have a form consisting of 20+ controls, for example buttons.
We want to create handlers for the On-click event for all of them.
The usual way is to go to the designer and double-click each button to have it automatically create the function.
Another way is to create them yourself in code, after the InitializeComponent() function.
Is the difference between the two?
1) In performance
2) In speed
3) Garbage collecting
The first way is easy but lately I've been thinking about the second because its easy to see (in one place) what controls have what events handled without going to the designer which is a real pain if you have the controls cluttered...
Creating them through the designer is exactly the same as defining them in code yourself.
What actually happens is they are placed within the InitializeComponent() method on the form, which is normally in the designer.cs file. So it's there, it's just a little more hidden from the developer.
This means that neither performance/speed nor garbage collection will be affeted in anyway :)
As the other answers stated, there is little to choose between the tow methods other then coding style.
I have worked on a project where the Buttons themselves were attributed data that allowed a generic event handler to determine the action required. This alows the Event Handler code to be nice and simple e.g.
foreach(Control ctrl in this.Controls)
{
if(ctrl is Button)
{
(ctrl as Button).Click += // generic Event handler
}
}
The downside of this approach is that it tightly couples the button with the event handler code. But in a limited scope application with a set of buttons that perform the same function, this could be a useful techinque.
There's no difference in performance speed or garbage collection. Whether you write the event hander button.OnClick += MyHandler or you double click in the designer and he generates that for you, it's just the same.
There might be a difference in typing button.OnClick += MyHandler and the Visual Studio generated button.OnClick += new EventHandler(MyHandler). Since there's a constructor involved. But that's just a marginal difference.
Why would there be any difference ?
When you doubleclick the button in the designer, to create an eventhandler, VS.NET will generate code to attach the eventhandler to the Click event.
Actually, the generated code will be the same as the code that you'll write to attach the eventhandler to the event.
Related
I wanted to add a GotFocus event to a Windows Forms Textbox, so I used the method described in this question; it works, but after I run my application a couple of times the piece of code deletes itself and I don't know why.
This is the code that keeps deleting itself:
txtID.GotFocus += txtID_GotFocus;
It disappears because you don't use conventions that are used by WinForms designer when you add event handlers.
It doesn't matter whether you use GotFocus or Enter event. If you (in your Designer.cs) manually add event handler this way:
txtID.Enter += txtID_Enter;
then it would always disappear from designer next time you move control on designer surface.
You must add event handlers this way:
txtID.GotFocus += new System.EventHandler(txtID_Focus);
txtID.Enter += new System.EventHandler(txtID_Enter);
and nothing would disappear because it's the way designer expects code to be.
Surely it's another evidence about why you should not touch designer generated code and should pay attention to this warning: do not modify the contents of this method with the code editor.
As a workaround use Enter event instead (which is recommended). Also you can assign the handler in your Load event of form.
EDIT
The reason is correctly mentioned by nikita, it's because you didn't use designer conventions. For more information see his answer.
At work, my old boss would insist we programmatically assign and remove event handlers from our controls in the code behind, rather than simply double clicking a button (for example).
We'd have an AttachEvents() and DetachEvents() method on every single form. I don't remember his explanation as to why this is allegedly better than assigning it from the Design View, and he's since been transferred to a different project. My new manager doesn't know.
I thought he said it had something to do with events not properly being removed from memory, but I really don't know.
So: What is the benefit of doing it this way?
Performance-wise they are the same.
But doing it in the code behind is a much neater way since you control when to AttachEvents() or DetachEvents()
But you have to be careful in terms of avoiding any duplicate event wire ups. These in turn might lead up eating memory, but prominently they would cause performance issues since the event handler would be called as many times as it was wired up.
Some event handlers such as timers need to be removed before leaving a form otherwise they would still fire, for example
timer.Elapsed += ...
and
timer.Elapse -= ...
Probably a good and clear way to remember to do it in this way.
Other than the implications of your own architecture, there's no difference whatsoever.
The designer will place the event subscriptions on the InitializeComponent method and you should not do any changes to that method because the designer might override them or crash if it's something it can't handle.
Usually, the event subscriptions are events the form subscribes from its children. When the from is closed/disposed, all the children are disposed and each child will dispose event subscriptions.
Problems arise when the form subscribes to outside components. Then the form becomes "attached" to those components and, if not unsubscribed, becomes a resource leak.
There's also the possibility of events being fired when the form is not ready to handle them.
I've used a mixed approach where events from child controls were subscribed in the designer (or carefully manually coded in the InitializeComponent method) and used the AttachEvents/DetachEvents approach for components outside the UI (or the scope of the form/control).
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.
I had a working program (Windows Forms Project) complete with buttons, labels, textboxes e.t.c. and the underlying code.
In an attempt to shortcut my work, I decided to add tab controls and move everything in my main form into tab 1 (cut and pasted).
As you can imagine it didn't work. I then got rid of the tab conrol and pasted everything back into the main form but the program doesn't work anymore.
Can someone tell me what's wrong please?
I'm working in MS V studio 2008 express
Thanks.
I have done this many times, but I usually just drag them into the TabControl. Maybe in the cut and paste operation your controls have become unwired from the event declarations.
The event handlers that you coded are still there. However, they are not associated with the control any more. I'm not sure if you're using VB.Net or C#, but the fix is the same - it's manual and tedious if you have a bunch of controls, but not too difficult. Here are the instructions for fixing a single button control, and you'll have to apply the concepts across the board.
These instructions are specific to C#. I can give you VB instructions as well as I've done this plenty of times.
Double click on the button to generate a new event handler. If the button is named Button1, the original event handler was probably called Button1_Click. Now it should be Button1_Click1.
Delete the Button1_Click1 function and compile. You'll get errors and if you doible-click on the error in the error pane it will take you to the form,designer.cs file to a line that looks like:
this.Button1.Click += new System.EventHandler(this.Button1_Click1);
Change this to
this.Button1.Click += new System.EventHandler(this.Button1_Click);
to point to the previously existing event handler, and the event handler will be fixed.
Possibly some of the events had code lost.
If you do it again it will probably work.
For an alternative method see my message
Can anyone tell me how to raise click event of button control (or for that matter for any event).
Platform: .net 2.0/3.0/3.5
Language: c#
Domain: Windows Application, WinForms, etc.
You can use the Button.PerformClick method.
Maybe the solution is much more simple:
Maybe you don't really want your code "to click the button".
Do you just want to run the code which is behind the button from another place in the form?
If yes, put the code into a separate method (like "DoActionXXX") and call the method from the button and from everywhere else where you need it.
You can also look into Windows Accessibility or some UI automation framework that allows you to programmatically cause UI controls to respond to user gestures. If a control does not offer a way for its events to be programmatically triggered like PerformClick, you can derive from that control and expose a public method like PerformnXXX that when called internally invokes the event handlers subscribed to a particular event.
button click and to new my manually window
ex.. dital.cs open the may window
I dont think sending click events is the best way from a design point of you just make your event handler call another function. That way you always have access to that function.
so ..
void myEventHandler(ObjectwhoSentTheMessage O, Event e)
{
MyOtherFunction();
//consume the event after if you wish etc
}