Why does VS2017 keep losing my derived controls? - c#

In my app namespace = DRT, I'm creating control classes (e.g., button, textbox) that derive fron their corresponding Windows control classes, e.g.,
internal abstract class DRT_Button_Abstract : Button
{
....
}
internal class DRT_Button_CancelSearch : DRT_Button_Abstract
{
....
}
internal class DRT_Button_StartSearch : DRT_Button_Abstract
{
....
}
All together I currently have 13 derived classes that derive either from one of my abstracts or from a Windows control class. After a successful build, I see my control classes (e.g., DRT_Button_CancelSearch and DRT_Button_StartSearch) on the Toolbox and I successfully drop them onto my main form. All is fine for a while, but ultimately, I'll go to open the main form.cs [Design] (i.e., the UI designer) and it will show the error The variable '{control property name}' is either undeclared or was never assigned. for some combination of my controls.
When I examine the main form Designer.cs file, the expected code for all the controls is present EXCEPT for the expected new statement. They are not present in the main form Designer.cs file. For example, I expect to see this.drt_Button_CancelSearch = new DRT.DRT_Button_CancelSearch(); but its missing
I've tried ignoring the error, proceeding to the UI designer windows to re-apply the lost controls, but the problem just repeats with the newly applied control
What the heck is going on? Is there a way to recover from this situation?

This is most likely a problem of the Designer not being able to clear/reload its cache. There is not much you can do. In the past I:
closed and reopened all designers that have user controls
put all the controls in a separate project (in the same solution)
put all the controls in a separate solution/Visual Studio instance and set a proper reference to the controls' dll (or even nuget package)
With the first two options I have had varying success. Reopening the designer is not very convenient and doesn't work.
That last option is the best but also the most annoying because every adjustment requires a rebuild of the project and update of the reference/package.
Also make sure that all controls that you create have public default constructors and function well when this constructor is used.

Related

What access specifier must be used for UserControl members when used with the WinForms Designer?

I created a larger UserControl and added it with Forms Designer to a form.
The application compiles and runs fine, until I edit something in the designer.
Then in InitializeComponent the
this.myUserControl = new MyUserControl();
line vanishes.
The user control itself gets declared and initialized. The problem is, that the instance creation is missing and when it comes to the initialization I get a NullReferenceException.
I have to add that I didn't touch the designer for a few weeks. During that time I changed a lot of public fields of my UserControl to internal or private. Everything worked fine until I tried to edit the form that contains my UserControl.
When I found the missing instantiation I took a backup and changed every membervariable of my UserControl back to public and the problem with the missing instantiation is fixed again.
Are there any known problems/restrictions according access specifiers used in Windows Forms UserControls when they are used in the designer?

Prevent Visual Studio from updating specific lines in Form.Designer.cs

I was wondering is it possible to prevent Visual Studio from updating specific lines that are changed by me?
For example i have separate resource only project (images, sounds, etc). I change some lines in Form.Designer.cs and make so all images are loaded from resource dll. But once i update Form it self everything goes back to default and all resources that were used by form gets copied to Form.resx file.
How could i solve this?
Nope.
As stated in the begining of the file, the *.Designer.* is an auto generated file. It's rebuilt every time that the file it depends upon is saved, so you should never change any code there that you don't want to be messed.
It is preferable to separate the code that the form designer generates from the code that you want to have some control over. The order in which you need to address this code can then be handled within the constructor of the form. Example:
namespace FormTest
{
public partial class Form1 : Form
{
private Label PostAddedLabel;
public Form1()
{
InitializeComponent();
PostInitializeComponents();
}
private void PostInitializeComponents()
{
if (!this.DesignMode)
{
PostAddedLabel = new Label();
PostAddedLabel.Left = 100;
PostAddedLabel.Top = 30;
PostAddedLabel.Text = "The Post-added Label";
this.Controls.Add(PostAddedLabel);
}
}
}
}
We can simply design the form within the designer, after a successful design phase we then can MOVE the declaration, assignments and related code that we want to separate to the PostInitializeComponents method.
By using the !this.DesignMode decision, the form will show the separated controls in Runtime mode. When in designer-mode these controls will not be shown, assuring that the system will not affect these controls when designing the form.
In case you want to use this methodology also in usercontrols, try to embed the "IsDesignerHosted" method over "DesignMode" from the following article: DesignMode with Controls
Hope this answers the question?
No. Visual Studio does not "update" the Designer file, it deletes it and writes an all new copy. No possible way to do what you want.
You should add your code to your code behind. It's the same class.

Winforms App Not Displaying Graphical Elements in Design Mode

I wrote a bunch of code in the .cs file in c# for a winforms application. The application runs fine, and everything is in it's place.
Something like this:
using..
namespace Temp
{
public class Temp : Form
{
Button b1;
TextBox t1;
Temp()
{
b1.Text = "Some Text";
b1.Size = new Size(50,20);
...
}
void function1()
{
// stuff
}
static void Main()
{
Application.Run(new Temp());
}
}
}
How can I modify my code (or fix it somehow) so that the design view displays the elements in their correct positions and view so that I can visually edit them instead of having to trial/error everything.
Edit for Clarification
My application runs fine. The problem is, that I didn't use designer to create the application and so in the designer view, the app is empty. But not empty when I run it, since everything is positioned programmatically in the .cs file. My question is, how can I fix this, so that the designer shows the objects correctly.
There is no quick fix other than to redesign everything?
So to get this shown within the designer you have to know how the designer works.
For every MyForm.cs there will automatically be a file called MyForm.Designer.cs be created. Within this Designer file there will be only one function called InitializeComponents(). This function will be called within the constructor of your MyForm.cs file.
The design viewer itself is responsible for the Designer file, so any change to this file while the design view is open would normally be discarded. Also if you put some code into the designer file that is not needed be the designer will be truncated.
So the next question is, when will this truncation happen? When you freshly open the design viewer of a form, it will read in everything from the Designer.cs file without making any changes. If you make any changes onto the form by the designer the complete file will be rewritten with all the settings already read in including your latest changes.
This behaviour can be monitored if you open the designer file also as source code view, make some little changes in design mode and afterwards take a close look at the left of the source file. There will be the changes marked with a yellow or a green marker.
Now after all this stuff of informations, you can try the following procedure to get your code into the designer:
Open the design view and put some simple control onto your form (e.g. TextBox)
Save and close the design view and open the Designer.cs file as source file
Copy all your variables name of your controls at the end of the file, right below the textBox1 line
Copy all your control property settings within the InitializeComponent() function right below the property settings of the TextBox
Copy all your control constructors to the top of the file, right below the constructor of the TextBox
Save the file and open your form in design view
Select the dummy TextBox on the design view and delete it
This change within the DesignView leads to a complete rewrite of the designer.cs file, ordering all your manually added stuff the right way.
So this is the way to go. Last but not least another little trick:
Every programmer uses the using-statement to not write the whole path to every class (like System.Windows.Forms.TextBox), but the designer writes always the whole path. To make it a little easier for your copy and paste session you can also add a using statement at the top of the file. After saving and changing something in Design View all this stuff will be re-written automatically. So you don't need to add all this paths manually while your adding your stuff to the Designer.cs file.
Your best option is probably to use the properties panel in the designer to set the positions etc (or maybe just drag them?).
You could go digging around in the designer file for the form (something.Designer.cs), but this isn't a fantastic idea because it can be pretty sensitive to changing things in ways the designer doesn't expect. Having said that, it looks like you're not actually using the designer to make your form (the class would be partial, for one thing), in which case you're SOL.
In that case, you need to copy the designer code from CS to designer.cs. So that you can use designer. I think this is the simplest approach.
Looks like this file was hacked from a class file instead of being generated by the system when you create a new winform.
You need at least an InitializeComponent(); call in your constructor. However you are missing a lot of other code that is generated for you when you create the file such as Dispose().
Best bet would be to right click your project in the solution explorer and click Add Windows Form then start over.

How to put an extended WinForms Control on ToolBox

I plan to add functionalities to TextBox with the following:
public class TextBoxExt : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
}
}
The question is how can we use this TextBoxExt? Is there anyway to get this class onto the ToolBox so that we can just drag and drop it onto the form? If not, what is the best way to use the TextBoxExt?
Build you project with TextBoxExt, make sure it compiles ok.
With the form that you want TextBoxExt on, open the toolbox, right click and select "choose items"
Browse to you .exe or dll that you compiled in 1)
make sure that TextBoxExt has a tick next to it, press ok
TextBoxExt should appear in the toolbox, drag it onto your form
(There is another way of doing this, opening the designer file and renaming the instances of TextBox to TextBoxExt but manual editing of designer files can be considered hazardous by some)
I know this is super old question, but maybe still useful for someone else that has same problem like me - as it's still on the top Google :)
You might interest to use ToolboxItemAttribute (http://msdn.microsoft.com/en-us/library/system.componentmodel.toolboxitemattribute(v=vs.110).aspx).
I did this at my end to resolve the problem.
[ToolboxItem(true)]
public class PanelTitle : LabelControl {
// Whatever code to override LabelControl here...
}
Rebuild the solution and the extended control should be shown in the toolbox.
Any custom control in your project should show up in the Toolbox automatically. I have found that sometimes the controls won't show until you close a re-open Visual Studio. I assume the issue has something to do with caching of the contents of the Toolbox.
You need to add a constructor to your derived class.
public class TextBoxExt : TextBox
{
public TextBoxExt()
{
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
}
}
Your control should appear in the toolbox for your solution automatically. To have it appear for other projects, you have to do Choose Toolbox items, as others have said.
If you want to provide special design-time functionality, then you will also need to provide some additional designer related attributes and probably your own class derived from ControlDesigner.
I fell into this trap just a couple of hours ago.
I've got a .NET 2.0 Windows Application project with some custom UserControls; it worked fine.
So I decided to order my files in subfolders, to make my project a little bit cleaner.
After that, Visual Studio 2010 designer stopped loading my forms, and ToolBox won't show my controls anymore.
I freaked out, moving back source files in project root, resetting ToolBox, but nothing seemed to work.
After that, I remembered I used ReSharper "Remove Unused References", so I tried to put back unused reference, in particular System.Data: problem solved! :O
I can't say you why, but this worked for me.
Hope my experience can help someone else. :)
Bye,
Nando
I created an empty constructor for my custom implementation of UltraGridBagLayoutPanel. Although david.healed is right it isn't necessary, it is quite useful to put a breakpoint in to check that when the form initialises it is using your class to implement your custom control.
It would have been a lot easier to edit the designer file, but I tried it and changed both the field type for the control and also changed the assignment of the field to a new instance of my custom control.
private Infragistics.Win.Misc.UltraGridBagLayoutPanel ultraGridBagLayoutPanel1;
this.ultraGridBagLayoutPanel1 = new Infragistics.Win.Misc.UltraGridBagLayoutPanel();
to
private Athia.Reports.ultraGridBagLayoutPanel1 ultraGridBagLayoutPanel1;
this.ultraGridBagLayoutPanel1 = new Athia.Reports.ultraGridBagLayoutPanel1();
Doing this destroys Visual Studio every time, and to fix it requires using a text editor to put it back again. Therefore unless anyone can describe what is wrong with my implementation of this approach, perhaps calling the class the same as the control name isn't a great idea, I think the only safe and reliable way to achieve this is as Calanus describes in steps 1 to 5 or as an small deviation from that as Rob Windsor rightly points out restarting VS will bring the control into the Toolbox automatically. Unfortunately for me I then have to change all of the child controls over from the original class to my customised class :-(.
Within the same Solution this should work automatically. However, I have found that if the Target Framework aren't matching the Toolbox does not populate. ( I'm assuming really Reference needs to be of version same or lower than target of Reference. ) ( I did get a warning about non-matching Frameworks )
By making these the same Target Framework, Recompile, Restart VS. the control populated correctly. ( I also added the ToolboxItem(true) Attribute)

.NET Windows Forms design time rules

I have an object that starts a thread, opens a file, and waits for input from other classes. As it receives input, it writes it to disk. Basically, it's a thread safe data logging class...
Here's the weird part. When I open a form in the designer (Visual Studio 2008) that uses the object the file gets created. It's obviously running under the design time vhost process...
The odd thing is I've not been able to reproduce the issue in another project. I'm not sure what the rules are for code that gets executed in the designer and code that does not. For example, creating a file in a Windows Forms constructor doesn't actually create the file at design time...
What is the explanation? Is there a reference?
The constructor of a control or form does not get executed when editing that class in the designer (nor does OnLoad get called). I've occasionally used this to set one value in the designer (eg. making its child controls all Visible in the designer) but override some of them to a different default value in the constructor (eg. hiding certain child controls which will only show in certain circumstances, such as an indicator on a status bar).
However, the constructor does get executed if the control is placed as a child on another control or form in the designer. OnLoad gets executed as well. This may be how your logging code was getting accidentally triggered in the designer.
For detecting design vs runtime, an answer to another question has screenshots of some emperical tests showing the values returned by some common approaches. It appears that a child control of a child control (two levels down) of the form or control being edited in the designer sees its own DesignMode == false, so the normal property check will fail to protect code (eg. in the OnLoad method) for controls nested within a control added in the designer. If you were checking DesignMode as one would expect, it could be the nesting which caused it to get around that check. It also always sees DesignMode == false within the constructor.
Also, note that the LicenseManager.UsageMode check only sees DesignTime within the constructor; when OnLoad is called it is within a RunTime LicenseContext. The most complete solution seems to be to check LicenseManager.UsageMode in the constructor of the control or form (or component) and save the setting to a member variable or property which you can check later to avoid running code that should never run in the designer even when nested. There's also another approach in another answer to that other question which accounts for nesting but only works outside the constructor.
You can check the UsageMode of the LicenseManager, to check if the code is in design time or not.
System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime
Here is a quick example:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Test
{
public class ComponentClass : Component
{
public ComponentClass()
{
MessageBox.Show("Runtime!");
}
}
}
When this component gets add to your form in the designer, you will immediatly get a message box.
To prevent this you can add a simple if statement to check if the code is not in design time
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Test
{
public class ComponentClass : Component
{
public ComponentClass()
{
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
MessageBox.Show("Runtime!");
}
}
}
}
After adding the if statement, the messagebox no longer appears when the component is added to the form via the designer.
Well, since this has been resurrected anyway, here's the function I use to determine whether I'm in design mode:
public static bool IsAnyInDesignMode(Control control){
while(control != null){
if(control.Site != null && control.Site.DesignMode)
return true;
control = control.Parent;
}
return false;
}
This handles the case where the control is a child created by another control. The DesignMode property is only set for controls created by the designer itself.
You could also use this to check if the Visual Studio Designer is running the code:
public static bool DesignMode
{
get { return (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"); }
}
Then in Form_Load:
if (!DesignMode)
{
// Run code that breaks in Visual Studio Designer (like trying to get a DB connection)
}
However, this is less elegant than using the LicensManager.UsageMode, but it works (until Microsoft changes the name of the process Visual Studio runs under).
There are some things you shouldn't do with the designer. I don't have any hard evidence, but I found that the Windows Forms designer hates it when you take away the default constructor from it. Just go ahead and create new overloads, but leave the empty constructor in place.
Also try to avoid doing Form_Load events in base classes you inherit from.

Categories