Manual editing of *.designer.cs file - c#

I'm aware, that the .designer.cs file contains data generated by the visual form designer in Visual Studio. However, I have some additional methods though, which I want to put into the .designer.cs file as well, because these are responsible for lower-level form handling (for example, pieces of my visual state manager).
The InitializeComponent method inside the .designer.cs file has a comment stating, that it is automatically generated and should not be modified by user. Does this restriction apply only to that method or shouldn't the .designer.cs file be edited by user at all? I've noticed, that among others, it contains the Dispose() method, which the user might want to modify - what suggests the first option. I want to be sure, though.

You should never modify .designer.cs. Period. Your changes will be overwritten without mercy.
Update: To be a bit more helpful, C# since v3 (VS 2008) has included partial methods, which many designers will now use to let you implement custom behavior.

I think the other answers are simplifying too much.
First of all, I totally agree that it's almost always a bad idea to edit a .designer file, but there are a few cases where I've done so, feel it was good and proper, and didn't get burned.
Say I create a label and accidentally double click. Designer creates a method in my main .cs file which I then delete:
private void label1_Click(object sender, EventArgs e)
{
}
Well, now the code won't build unless I also delete the following from my .designer file:
this.label1.Click += new System.EventHandler(this.label1_Click);
Less frequently, the order in which things are added to a form or panel (or menu!) matters, and it can be easier to change this order in the code than in the Designer GUI. In my experience VS 2010 always picks up on this, updates its GUI's info, and redraws its preview. Just remember to focus on the Add() methods--the order variables are declared in generally doesn't matter.
Ditto if you set a property that causes a line to be added to the .designer file, deleting the line gets picked up quickly and Designer refreshes. Maybe it's wiser/safer to use the GUI to change the property, but I think deleting the line is cleaner.
Code that is not inside this region, #region Windows Form Designer generated code, will only get generated once. It is safe to move, and as others have recommended elsewhere (https://stackoverflow.com/a/6527072/1593924), moving the Dispose(bool) method out actually can make a lot of sense, if you're modifying it or adding a Dispose() method that should ideally sit next to Dispose(bool).
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
DISCLAIMERS:
That said, I've only tried VS 2010 Ultimate; your mileage may vary on 1-3 above, but 4 should be safe as long as the .designer is a partial class with Dispose(bool) outside that #region. I also make sure the latest good version of a .designer file is committed into the source repository before messing with it.
By admitting to having gone along with the Dispose(bool disposing) pattern, I'm not meaning to promote that approach. There seem to be good reasons to simply use Dispose() in most cases, and only do more for unmanaged resources, each of which is encapsulated one-to-one in a dedicated Disposable object.

this instruction applies to the complete designer.cs file.
As all the code written in it is automatically generated.
You should not do any modifications in this file as it can be recreated anytime... this will remove your methods...
If you want to keep the code separate from the form code file, then I suggest to create another file which contains a partial class where you can put all such methods...
Hope it helps...

Leaving designer.cs in peace not only prevents your changes from being overwritten, but also helps other developers by saying that nothing unexpected should come out of it. That being said, there is at least one exception I can think of and that is the one mentioned by author of the post: extension of Dispose() method. To my knowledge this code - once generated - will not be overwritten.
However, in my opinion much better solution is to override the Dispose method and than call the base.Dispose(), so that we leave designer.cs clean.

Partial designer form class it's used by Visual Studio for placing all code need for build the control.
The method InitializeComponent() can't be overwrite: it's used by designer editor for render a preview of your form!
Try in a new project: resize your form, add a label and a button and rename the InitializeComponent() method + re-compile.
Your form back to default size!
If you need to call code by form loading, just override OnLoad() virtual method, if you need to call code by form showing, simple override OnShown() virtual method.
Remember to call the base.Method() at begin of it override.
Hope this little my experience can help!

Related

C# (object sender, RoutedEventArgs e) Properties

Visual Studio keeps saying (object sender, RoutedEventArgs e) properties are not used and to remove them. But if I do, it errors out the MainPage.g.cs reference. What should I do?
//MainPage.Xaml.cs
private void TextBoxSingleArray_GotFocus(object sender, RoutedEventArgs e)
{
var textBoxSingleArray_GotFocus = e.OriginalSource as TextBox;
textBoxSingleArray_GotFocus.SelectAll();
}
//MainPage.g.cs
//If I remove object sender, this will display error
((global::Windows.UI.Xaml.Controls.TextBox)this.TextBoxSingleArray).GotFocus += this.TextBoxSingleArray_GotFocus;
There are two ways to solve this.
1) Remove the name of the parameters using "discards" .
REf. https://learn.microsoft.com/en-us/dotnet/csharp/discards .
The error you see is due to you are not using those parameters inside the method.
2) Disable the warning:
Ref https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-pragma-warning
Ref http://www.blackwasp.co.uk/SuppressWarnings.aspx
You just cannot simply remove the parameters since TextBoxSingleArray_GotFocus is a referenced event that requires to receive those two parameters. Even if you don't use them.
Hope it helps.
Juan Simon
I've seen messages like that (not in that particular case, though) from ReSharper (do you have that installed?), but Visual Studio itself may also do something similar.
Often, messages like that can help you keep your code cleaner... or sometimes catch bugs because it highlights when something you thought was being used is actually being missed. But in some cases, such as when creating a library with a public API but that isn't fully used within the same solution and leaves some "public" members unused, a suggestion such as "can be made private" isn't really true--it just has no way of knowing that.
This sounds like a similar case. You have arguments which are required for an event handler, but until it is used as an event handler somewhere within your code it wouldn't know that and might warn you that they aren't being used. Or, properties on the RoutedEventArgs aren't being referenced within the handler (or elsewhere in the code that it can see), so it gives you that warning and suggestion. But really, they are required--just perhaps not within your solution--and you can't really remove properties from a defined event args type that comes from WinForms, anyway.
But, you generally want to take note of messages like and consider whether the suggestion applies or if you have missed using something you should--or maybe you're just still in the middle of coding it and it might go away once you're done. If it's really a warning (shows up in the Errors box after a build) you may want to suppress it around the unavoidable cases where you know you don't want to access the other properties to "fix" it, but as #HereticMonkey commented, it's probably just a suggestion and not an actual warning. The main reason to suppress it is so that other, real, warnings aren't missed and can be attended to (or similarly suppressed if not important). Either way, as long as it's not preventing it from building successfully, you don't have to follow the suggestion--because it's not always right.
I believe you can get VS to be quite about this by naming your parameters _ and __.
Alternatively, you could add a SuppressMessage annotation to your method.

Injection custom class in Form windows C#?

I built the standard windows form application. Just one form with button "Check data".
After click that I send request to Http server and get back data.
I have to execure at once when form was built.
For this I have created separated custom class: CustomRequest.
How to inject this class inside:
public Form1()
{
InitializeComponent();
// Create instance of my custom class here
}
Is it good practic to inject direectly? Does it break SOLID priciples? Or I need to create also abstract class and use custom class through it?
`
It really depends on your use case. Ask yourself these questions:
Does my code perform operations on the UI?
Does my code require information from the form or about the form?
Does my code perform a time consuming operation?
If the answer to any of these is yes, then I think the best solution is to override the OnLoad method and execute the code you want there. This is debatable regarding the time consuming code case. However, if your code performs any operation on the UI, you should definitely take this approach.
protected override void OnLoad(EventArgs e)
{
// Your code here
}
NOTE: You can also subscribe to the Load event, which will yield a similar result, but is only recommended for very specific cases.
If your code isn't related to the UI itself, then using the constructor is the simplest solution, and will likely work just fine. However, there are a few caveats to this approach. First off, you have to remember that the constructor runs when the form is instantiated, regardless of whether or not its ever displayed. Additionally, make sure that you place that code after the call to InitializeComponent(), to prevent any delays in opening the form.
I'm giving you the succinct version. For a more detailed explanation, I recommend you give this and this answer by Hans Passant a quick read. He has some great information about the difference between Load and OnLoad, as well as when to use one of those two and when to use the constructor.

ArgumentException when trying to add a child to Canvas

I have some mysterious ArgumentException I have been beating the whole day - still have no idea why does it happen.
I have the next simple method in my MainPage:
public void FavsRefresh()
{
favsCanvas.Children.Clear();
for (short i = 0; i < (App.Current as App).favUnits.Count; i++)
{
FavsItems tmpUnit;
(App.Current as App).favUnits.TryGetValue((App.Current as App).ids[i], out tmpUnit);
Canvas.SetTop(tmpUnit.subCanvas, i * 120);
favsCanvas.Children.Add(tmpUnit.subCanvas);
}
}
Here tmpUnit is an instance of my class FavsCanvas. Its code doesn't matter - it merges some elements into Canvas, which is called here subCanvas and a series of them must be added into parent Canvas, called favsCanvas.
The sense in all this, that we have several items initially and the user may delete existing and add new. Every time an item is deleted or added I call this procedure (including initially program loading).
The joke is that it works during loading and when I call it from another pages, but when I call it from class method throws an exception, besides it adds the first element properly and refuses to do that with others.
Every item has unique name, I even tried not to use names at all or use random ones - not a chance. I have no idea why this exception appears?!
I call this method using following:
MainPage.MPInstance.FavsRefresh();
This way works good from another pages, but from class - fails. I even left only one line (simple reload those items in Canvas):
private void FavMenuItem_Click(object sender, RoutedEventArgs e)
{
//Delete favorite
if (((MenuItem)sender).Header.ToString() == AppRes.FavsMenuDeleteFav)
{
MainPage.MPInstance.FavsRefresh();
}
}
The fun is that this code worked when I wrote it first a couple weeks ago, but now somehow stopped.
Another thing I tried is to make this particular call from a method in App.xaml.cs, which in its turn is called from the class, but it didn't help either.
In fact I have studied most of parameters - everything is the same in both cases: when it works and when not, except the place from where the method is called. But I don't see any proper alternative.
--- added 05 Aug.
I am not sure if it is important, but it always point the next line after the line where exception is thrown:
(the forum does not allow me to post images, so here.
I tried to move this method to class both to class itself and to App.xaml.cs - the same problem.
It works properly when is called during loading (my MainPage is Pivot and this page which contains this favCanvas is one of the pivots, but not the first) and when I call it from another page while overriding its OnNavigatingFrom. And when it is called while the the MainPage and this pivot is active. May be something with that?
Well guys, I still can't catch the reason itself, but at last have found a dirty way to walk around.
The page, for some reason, does not like to be modified when it is active (at least this way). So for now I am forced to simply redirect to another page, where I just call my method and then go back.
If you have some ideas, they are still of demand as my current was is like a crutch and I dislike it

Using XmlDocument.Save() Effectively

I'm working with a .XML document in C# to which I'm selecting nodes from, adding nodes to, and deleting nodes many, many times over a span of my code.
All of the XML editing of this document is contained within a class, which other classes call to.
Since the Data Access class has no way of telling if the classes using it are done with editing the document, it has no logic as to if/when to save.
I could save after every modification of the document, but I'm concerned with performance issues.
Alternatively I could just assume/hope that it will be saved by the other classes that use it (I created a one-line public method to save the document, so another class can request a save).
The second option concerns me as I feel like I should have it globally enforced in some manner to avoid it being called upon and modifications not being committed. To this point there will never be a case where a rollback is needed; any change is a change that should be committed.
Does .Net (Or coding design) have a way to balance performance and safety in such a situation?
If you always want to save the changes (just don't know when) then you could add the save command to the class destructor. This way you know the changes will always be saved.
If you need additional help or want an example please leave a comment, otherwise select an answer as correct.
Update: It has been brought to my attention that the class destructor may fire after other objects (like a FileStream) have already been disposed.
I recommended that you test for this condition in your destructor and also that you implement and use the IDisposable interface. You can then subscribe to the either the Application.Exit event or Application.ApplicationExit event and call dispose there.
Be sure to keep the code in the destructor (but make sure you have it in a try block) in case the program crashes or there is some other, unexpected exit.
Basically your question says i all: You need to save, but you don't know when, as the knowledge about the savepoints is otside your class.
My recommendation is to wrap your calls - assuming you have something like public void MyClass.SomeEditing(int foo), create a wrapper like public void MyClass.SomeEditing(int foo, bool ShouldSave) with shouldsave defaultingto true.
This way, a consumer of your class can decide, wether he wants an immediate save or not, chosing false if he knows, an immediately following other edit will cause the save. Existing code, which calls the "old" API is protected by the default of "save imediately"

Why does the Visual Studio IDE sometimes initialize the "this.components object: and other times not?

I've recently noticed some behaviour with the Visual Studio Designer (C#) that I don't understand and was wondering if someone could clarify...
One some of my Windows Forms, the first line of the designer generated code reads;
this.components = new System.ComponentModel.Container();
When this is the case, the dispose method, in that same designer file, the dispose method places two "Dispose" calls within the case "if" condition as follows;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
base.Dispose(disposing);
}
}
i.e. Nothing is called unless disposing is true, AND components is not null.
On some other forms, that first line in the designer generated code is missing. In these cases the base.Dispose call is outside the "if" condition as such...
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
I have noticed this while tracking down a bug with a form not closing, where this.components was null, yet the base.Dispose call was inside that condition (I suspect the designer code had been tampered with but that's another story.
What controls this behaviour?
(Some earlier forms in the project were created in VS 2005 and we now use VS 2008 - clue?)
This is reproducible behavior. When you create a new form, it starts out with a skeleton that includes the this.components constructor call. When you then add a component (say a Timer) and remove it again, the designer regenerates the code, now without the constructor call. That isn't a bug.
Fwiw, the skeleton code is generated by Common7\IDE\ItemTemplates\CSharp\Windows Forms\1033\Form.zip\form.designer.cs
Seeing the base.Dispose() call inside the if() statement is a bug. That might be self-induced. Or it might be a beta version of the skeleton code. VS2005 does it right. Do check the ItemsTemplatesCache folder.
6 years later and this problem still occurs. I've managed to track down at least one cause for it happening.
When testing if your component has a constructor that takes an IContainer, System.ComponentModel.Design.Serialization.ComponentCodeDomSerializer caches a reference to the Type of IContainer for your project. If you then save an object for another project within the same solution, or perhaps when you have made some other types of changes in your project, ComponentCodeDomSerializer can no longer find the constructor as the Type of IContainer is no longer equal to it's cached Type.
If this is happening lots for your project, there is a very ugly workaround. Add this VB or C# VisualStudioWorkaroundSerializer class to your solution. Then add the attribute DesignerSerializer(GetType(VisualStudioWorkaroundSerializer), GetType(CodeDomSerializer)) to your component. Whenever your component is saved, this custom serializer will detect the problem, fix it, and force you to save again whenever this issue is about to occur.
Interesting glitch! It does indeed sound like a bug in one version of the designer / templating. Of course, if you think the designer code had been tampered, all bets are pretty-much off anyway...
However, in VS2008, it generates the undoubtably correct version:
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
So the base Dispose(...) is called. I haven't got VS2005 handy to test it, unfortunately. However - it doesn't initialize the components until it has to - the declaration is:
private System.ComponentModel.IContainer components = null;
And then if it is needed, it is populated in InitializeComponent:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
//...
}
I guess with this construct it only has to maintain InitializeComponent (and not the fields itself).
I have seen this happen, and I've also occasionally got warnings about from the Dispose method about components either never having its value assigned, or not being defined.
I think it is a combination of two things:
Slightly different code generation between versions of Visual Studio
The Dispose method is only generated if there is not one already in the file, whereas InitializeComponent (and associated declarations) is generated each time
This results in an InitializeComponent/declarations section that is out-of-whack with the Dispose method.

Categories