Using VS2013 Pro, WinForms, the debugger keeps deleting my event handlers. (I place them inside the Form.Designer.cs file)
I've only started noticing it recently and I'm positive I haven't changed any settings.
Can anyone else replicate this or is it just something on my system?
Steps to replicate:
Create new project C# WinForms
Add a split container > Inside panel two of the Base container, nest another split container.
In the Form.Designer.Cs file, hook up a Click event handler to the nested panel 1 container.
Run. -Click container - should work fine.
Exit Debugger > Change color property of the nest panel 1.
Run > Can no longer click?
Inspect Code > Event Handler has been deleted?
If you added your event handler manually then anytime you change something from the Designer the Form.Designer.cs is regenerated and will delete your event handlers (the ones added manually in the code)
What you need to do is to add the event handler from the Control properties.
For example if you code this in the Designer:
myControl.Click += myClickHandler;
it will be deleted anytime you change something in the designer, because the whole .Designer.cs file is regenerated and for some reason the VS is not aware of the event handlers added manually.
You;ll see that if you add the event handler from the Control properties window (in the designer) the generated code will look like this:
myControl.Click += new EventHandler(myClickHandler);
Another workaround is to add the handler outside the .Designer.cs class, but the easy way is to add the handler from Designer :).
Related
I'm having a strange issue that maybe being caused by my ignorance.
I have a treeview with an .AfterSelect and any time that i change the design of my form (in the deign view) the code gets removed for some reason.
here is my code
this.lstTreeView.AfterSelect += LstTreeView_AfterSelect; < this is the code that gets removed
this.lstTreeView.Location = new System.Drawing.Point(194, 56);
this.lstTreeView.Name = "lstTreeView";
this.lstTreeView.Size = new System.Drawing.Size(220, 498);
this.lstTreeView.TabIndex = 6;
this is the code that it allows to work.
private void LstTreeView_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
TreeNode CurrentNode = e.Node;
string fullpath = CurrentNode.FullPath;
MessageBox.Show(fullpath);
NrDirSearch(fullpath);
}
if anyone can give me some advice on why the .AfterSelect is being removed that would be really helpful.
I suggest you:
in the windows form designer, click the tree view to select it
in the properties grid click the lightning bolt and scroll to find the AfterSelect event
right click the name AfterSelect and choose reset
hit save all
Close out of the soution entirely/shut down visual studio
restart/reload the solution
Go back to the AfterSelect event as above, the box for which should be empty
click the drop down and choose your existing event handler
save all, quit and restart vs and check that the setting stayed
If you're finding it didn't stick, check that you don't have your designer open in another program e.g. A text editor that keeps autosaving an old version of the file that lacks the event handler?
Incidentally, the above process is how you add event in Design view - click the relevant control, lightning bolt, scroll to event wanted, double click the name of the event and you will be transported to your own code behind with a new named eventhandler created and ready to be filled
If you don't write any code in it, and go back to the designer and Reset the event as per the bulleted list instructions then your event handler method in your code will disappear. If you write code into the event handler then it is not removed when doing a reset, only empty handler methods are removed during reset
Side note: be careful with Undo if you see a message saying something like "performing this undo will cause a loss of work elsewhere" it usually indicates that the windows form design or designer.cs code will change as a result of actioning the undo
Designer files are safe to edit manually and it's sometimes necessary if the contents have gotten into a state where they are crashing the designer. I most often encounter this when deleting event handler s from my code that are still referenced in the designer. A screen appears saying a problem is preventing the forms designer from appearing, indicating the error line in the designer file. I have additionally in the past edited the designer directly to set large numbers of properties without the faff of using the designer - be mindful not to have a windows forms designer open at the same time as editing the designer.ca file because the forms designer will probably overwrite your changes. So long as you keep in mind that opening the same file in any two different editors at the same time can lead to conflict and loss of work, and take steps to ensure that edits in one editor are reflected in another before proceeding with further edits in the other editor, you'll be fine :)
Edit: having said that paragraph above, Mickey D made me realise an important point I'd overlooked:
The designer.cs file is read by the forms designer and uses to build the contents of the form, buttons, properties etc. As such if you are going to edit the designer.cs in a text editor you should limit your edits to only those things the forms designer can make use of, understand, represent and preserve when it next writes the file. Adding a line to set a button to enabled is fine. Removing a line that is causing it to crash is also good. Putting 27 methods that implement your entire program's database access strategy in is not a good idea as it will not be heeded or used to build the form when the designer reads the file and hence lost when the designer writes the file. If you're unsure of the difference between what will and won't be preserved stick to removing or fixing existing lines only rather than adding new lines of code
You should never[1] modify *.designer.cs files. They are code generated. Any changes you make are subject to being overwritten.
Instead either use the WinForms GUI Forms Designer to visually setup event handlers or you can do so in code in your form’s code-behind .cs file.
There are plenty of resources on the Net on how to use the WinForms designer.
[1] see Caius Jard's comment below for an exception to the rule that I concur with
This drives me nuts. In the Visual Studio WinForms designer, if you double-click a control it will produce a XXXX_Load handler for that control. This is never, ever, what you want. You want Click event or a Changed event or more likely to go to the existing Click event. You do NOT was a new Load event. It is worse because a double click can happen by accident. You click once, then again - bingo a Load event handler. I use a pen-tablet combo and double clicks are very easy!
Can someone tell me if there is a way to stop this happening. I would like a Click handler. I would settle for nothing happening.
One way to achieve that is inheriting the control and modifying the DefaultEventAttribute.
Specifies the default event for a component.
[DefaultEvent("Click")]
public class MyRadionButton : RadionButton {
}
But some care/extra work may need to be done when you override a control. You need to keep that in mind when using this approach.
In addition to Mehrzad's answer, you can completely disable it by passing an empty string to the DefaultEvent attribute:
[DefaultEvent("")]
public class MyCustomControl : UserControl
{
}
This works because the default control designer uses the ComponentDesigner.DoDefaultAction when the control is double clicked. By default, this uses reflection to look up the method signature of the default event. If it can't find it, it doesn't do anything.
I have a basic understanding issue that is there any difference between :
#adding a click event to form_load method of windows forms like
viewToolStripMenuItem.Clicked += viewToolStripMenuItem_Click;
and
#adding a click event to form1.designer.cs as:
this.viewToolStripMenuItem = new System.Windows.Froms.ToolStripMenuItem();
this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44,30);
this.viewToolStripMenuItem.Text = "View";
this.viewToolStripMenuItem.Click += new System.EventHandler(this.viewToolStripMenuItem_Click)
Sorry for question repeat in advance.
Never alter .designer.cs code because it has been generated by the tooling (Visual Studio), which means that in some cases your code might get wiped out!
If I'm not wrong, the code from the form1.designer.cs should be called by InitializeComponent. Check that this is called in the constructor of the form class: add your event handlers just after InitializeComponent call.
As #Sayse has pointed out, my warning mightn't be useful if you're adding these event handlers using Visual Studio designer (i.e. configuring control's properties in the designer view). If you're in this case, you can either leave your code as is.
This is a simple scenario:
I add an event to a control on the form by double clicking on its field (in Events part). But, then I decide that it was unnecessary and delete the automatically generated method. I'll run the program and it gives an error telling me that the event still exists in the InitializeComponent() and I must delete it from there.
So, is there anyway to avoid deleting the event "manually"? Is there anyway to fully delete it without leaving any trace (specially in InitializeComponent())?
Update: Also, another question arose:
When I delete the method from the code, the method name in the event field will disappear. So, if the InitializeComponent() is linked to these events, why isn't it updated with the empty event field?
You should use again the events grid and right click on the event you have inserted.
Select the Reset Menu option. This will remove the event handler assigned in the InitializeComponent and the code of the emtpy event in the code designer.
Note, that if you add code at the event, Visual Studio doesn't remove the new code.
The best way to do this is through the Properties grid in the Designer. You can click the Reset button or just delete the text and it will remove the event hook-up in the InitializeComponent() method. If your method is empty in your code behind, it will also delete it there:
It makes sense that you would have to manually delete the method body if it contains code in case it accidentally got Reset in the designer or if your method is referenced from some other part of your code. Visual Studio is gong to err on the side of caution.
If you delete the method body first, the reason it is not deleting the references to it probably in part has to do with cutting-and-pasting code. If you wanted to move the method to a different place in your code, the acting of cutting it would sever the references to it. After you pasted it, then you would wonder why your event was no longer be called. Again, error on the side of caution since it's not that difficult for the developer to track down extraneous code.
This pertains to C# 2017. So hopefully it would help others.
I'm new to C# (or at least back to code it) and ran with the same issue.
I commented out the event that I did by mistake. Then in the Error list, you will find an error there because that event is missing. Double click on it. It'll take you to the Designer code that "wires" the event. Once there, find the unwanted event and comment it out/delete it. Take care!
Look at the properties window when you select the Control. Click on the little flash and you'll see the Events listed, along with your event (Click or whatever), and your event will have the name of the assigned method behind it. Just delete that method.
That deletes the method, only if it's empty and otherwise unused though, which is quite reasonable. After all you might have put a lot of work into that event handler. (note: Just tried it again and apparently it doesn't always delete empty methods even though it did a few minutes ago. weird.)
In the designer you go to the events tab for the control in question, select the event that has the unwanted handler; and delete the name of the handler. Then save the form again.
This doesn't delete the method itself I think, (possibly unless it's empty or just been added).
Update
I dare say the reason for why it nearly always doesn't delete the method is because it could be used as a handler on another control's event. After all, in the UI you only asked to remove one event's handler; not every handler bound to that method. Then there's the question of whether the back-end code is dirty (i.e. unsaved) - checking whether the method is empty or not isn't reliable in that case. Yes, all of these could be worked around, but having to delete the method manually isn't exactly a hardship :) and at least this way VS doesn't end up deleting methods you actually want to keep.
Go back to the form and hit CTRL+Z.
I am currently transitioning from VB to C# and am having some issues with regards to registering my interest in an event.
When using VB it was simply a case of specifying that a method Handles and event, often this was generated by using the object events list. While I can easily use the Class.event += delegate in C# I am unsure where the best place is to place the code to do this.
Am I best placing it inside of the InitializeComponent() as per the generated code (say if you select the event in the from designer) or should I place it inside the constructor for better readability/maintenance. If inside the constructor, should it be before or after the call to InitializeComponent()?
When you are doing WinForm development (judging from InitializeComponent() function mentioned), usually you assign the handler using Visual Studio. You look up the properties of your control, click on the lightning icon to get the list of all events, find your event, and either double click on it (to create a new handler), or select existing handler from the list. Visual Studio will add the wiring of this in the generated code, so you don't have to worry about it.
I always create a private method called Init() and place it there, and then call that method from the constructor or the Form_Load event handler. It's semantically better, IMO, than doing it within the constructor proper. And you don't want to place it within InitializeComponent(), because next time you change something in your designer it's likely to delete any manually-added code there.
Sometimes Visual Studio's designer can mess up the code, so adding the event handlers within InitializeComponent can create a headache, it would be better to do it something like this
public Form1(){
InitializeComponent();
WireUpEvents();
}
public void WireUpEvents(){
this.fooEvent += new EventHandler(foo_handler);
.... etc ....
}
And make sure that you remove the event handlers in the Form's Dispose function also...
public void UnWireEvents(){
this.fooEvent -= new EventHandler(foo_handler);
.... etc ....
}
As you design the form, Visual Studio will change the code within the InitializeComponent() method located in form.design.cs, so it is imperative that you do not manually edit this code..
It depends, but most of the time, yes.
Use InitializeComponent when you want the event to be hooked for the entire duration of the Form (I'm assuming you're talking about Forms/UserControls/etc.). In other cases, you'll want finer grained control of when the Event is handled.
Keep in mind that you'll want to unhook all of these events (using the -= syntax) when you're Disposing the Form, or no longer want to handle the event. Keeping the event handler delegates attached is one of the most common managed memory leaks around.
Do not manually add code to the InitializeComponent() method. This method is code generated, so as soon as you change your form, any logic that you've added manually to this method will be wiped out.
I usually add a method to handle the Form's Load event and put my event registrations there.
If you have the InitializeComponent() method you're using the designer so you can bind events directly in the designer if you like. To do this, click the lightning bolt icon in the properties window and you'll see a list of all the events for the selected object. You can just type the name of the event in there and it'll create the code for you.
If you're not a fan of the designer, bind them after your InitializeComponent call and make sure you detach them when you're done (in Dispose()).
2 ways of doing this. You can either create you own method which you call in your Constructor which in turn creates the Event Handler, or you can just place them in your Constructor. Probably a good idea to remove the Event Handlers in your Finalizer/Destructor code.
I would place it after InitializeComponent, since you might be registering events against a child control/object, like a button, and you will want to be sure the object has been created already.
There will be cases where you wire up to events dynamically/conditionally in other places, such as in response to some other event.