Error Creating Control - Custom Control - c#

I have a custom control and it works fine...except that the control cannot be rendered on Design Time. ( I am using VS 2008)
I am thinking many people who develop custom controls encounter this problem...The error I get is "Error Creating Control - CustomControlName" Object reference not set to an instance of an object.
I want a work around. or at least debug this...(Since this is a design time issue how to debug?)
I have tried if( !DesignMode) code on OnInit, OnPreRender, RenderContents, CreateChildControls Methods ( I am just shooting in the dark)...
Help pls. I really hope this is not a VS bug!

BFree's comment is the most likely issue, for a control to display in the design view it needs a parameterless constructor as the design viewer doesn't know how you would normally instantiate the control.
If you do have a parameterless constructor, can you paste some code in to show what's happening?

As Glenn mentioned the first issue could be no parameterless constructor.
The second could be you are calling methods during the OnLoad or other methods you mentioned that have parameters that are not initialized or some sort of attempt at database calls etc that is normally done at run-time.
Unless they fixed this bug recently* and I'm not aware, something to keep in mind is the DesignMode property works for the first and second level of nested controls but beyond that it normally doesn't work right. (Such as form containing a UserControl[1] that holds another UserControl[2], the DesignMode works on the form and [1] but not [2]).
Also to agree with Glenn, seeing some of the code will help.
*From my very recent experience working with nested usercontrols it hasn't been fixed.

In your OnPreRender & CreateChildControls methods it's making a call to this.Page. You might want to try wrapping them in a
if (this.Page != null)
{
.....
}
Because I don't think you'll have a Page object at that point & I'm pretty sure PreRender & CreateChildControls will be called in design view. I haven't written custom server controls for a while though, so I could be wrong (been working in MVC lately).

Glenn, the error ur getting a VS bug and no fix has been released yet.

Related

NullReferenceException from DataVisualization.Charting.Axis.GetLinearPosition()

I have created a form that displays a chart using Microsoft's DataVisualization.Charting.Chart control (I use version 4 of the .NET framework). I also draw some annotations on the chart, and to locate them I need to know about the chart axes.
The code
myChart.ChartAreas[0].AxisX.ValueToPixelPosition(location)
gives me a NullReferenceException. The chart is definitely instantiated and I can set properties of the AxisX- for instance, myChart.ChartAreas[0].AxisX.Maximum = 1 works fine.
Drilling into the exception message, it looks like the trouble is in the GetLinearPosition method, which is something internal to the Chart control:
at System.Windows.Forms.DataVisualization.Charting.Axis.GetLinearPosition(Double axisValue)
at System.Windows.Forms.DataVisualization.Charting.Axis.GetPosition(Double axisValue)
at System.Windows.Forms.DataVisualization.Charting.Axis.ValueToPixelPosition(Double axisValue)
Does anyone have any insight to get me started fixing this? Thanks in advance!
This answer came in a comment to the question from Hans Passant:
That rings a bell. I think the trouble is that this can't work until
the control has figured out its data-to-display mapping. Which doesn't
happen until it needs to paint itself, in typical lazy fashion. Call
Update() first, something like that.
Which got me far enough to make this discovery:
You figured it out, Hans. The chart is on a TabControl tab, and I had
to bring that tab to front (with the TabControl.SelectedTab property)
before making the call to ValueToPixelPosition.

Follow-Up: Finding the Child of a Control

I believe the proper term is recursively. I have a Windows Form, and inside that I have a Tab Control, and inside the Tab Control are four Tabs, and inside each tab are multiple controls - Buttons, text boxes, etc. I want to change the cursor of every button to a type hand.
Below is where I have gotten so far with this inquiry:
foreach (Control c in tabControl1.Controls)
{
// The only controls that will be found here are the tabs themselves. So, now I must run a *foreach* loop through every tab found, and look if buttons are present.
}
The commented area explains my issue to some extent. I have found an example of a recurisively finding a control on a form but I am not sure why I would need to pass the contro's name as an argument as I am trying to find Every control of type button.
Here is the code that I found online:
http://www.dreamincode.net/code/snippet1663.htm
Thank you once again. I love hearing from all of you as it's an excellent learning experience for me.
Thank you very much for your time.
private void FindAll(Control myControl)
{
if (myControl is Button)
doStuff();
foreach (Control myChild in myControl.Controls)
FindAll(myChild);
}
I believe this will work. When you call it the first time, you'd pass in the form. The form isn't a button, but it will have children. Each child it has will be passed into FindAll(). If that control is a button, it will call doStuff() (you can set the cursor in there). Likewise if that control has any children, they'll be passed in.
You are correct, the term is recurisve (generally speaking, any function or sub that calls itself). So, in this example FindAll() will call FindAll() in a certain case.
Also, this is just sample code; you may want to check for null references depending on the nature of your application.
EDIT: Just as an FYI if you aren't familiar with recursion, it's pretty easy to get the dreaded StackOverflow exception. When you end up in a never-ending loop of calling yourself, you'll run out of stackspace and see the StackOverflow exception. Hence, the name www.StackOverflow.com
In this case, we don't have to worry because .NET prevents us from adding controls that create a circular reference. For example - this code will fail:
GroupBox g1 = new GroupBox();
GroupBox g2 = new GroupBox();
GroupBox g3 = new GroupBox();
g1.Controls.Add(g2);
g2.Controls.Add(g3);
g3.Controls.Add(g1);
I don't know if any of this makes sense, but hopefully it helps. Recursion is generally considered one of the 'harder' concepts to grasp for a lot of people. Then again, I'm not very good at explaining things.
You are correct that the correct term is recursion. In the link you have posted, it is indeed recursive because the function calls itself, which is a property common of recursive functions.
The function needs to take a Control instance because the function is trying to solve the problem "For a given control (which is the Control container that is passed in), find all controls inside." Notice how this method doesn't care about what 'level' the control is at, it can solve it regardless.
You are correct that if you ran the code in your example, it would not work. It would only pick up controls one level inside of the 'parent' control. This is why the function needs to call itself.
With the function calling itself, you get the following:
Call function with the outermost control.
Do I have any children?
If so, call the same function again for each child (which will again ask "Do I have any children?" on the child).
By calling the function inside the function, you will hit all levels.
WARNING: Just as a note of caution, recursion used carelessly can lead to problems. If you apply this on something that has 1000 'levels', your algorithm will take forever and possibly crash as you will run out of memory to handle it, since it is digging deeper and deeper (a stack overflow!). Separately, I suspect there is a better way to do what you are doing such that you don't need to use recursion, although it will work.
Hope this helps!

VS 2008 designer and usercontrol

I have created a custom data grid control. I dragged it on windows form and set its properties like column and all & ran the project. It built successfully and I am able to view the grid control on the form.
Now if i try to view that form in designer, I am getting following error..
Object reference not set to an instance of an object.
Instances of this error (1)
1. Hide Call Stack
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.GetMemberTargetObject(XmlElementData xmlElementData, String& member)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.CreateAssignStatement(XmlElementData xmlElement)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.XmlElementData.get_CodeDomElement()
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.EndElement(String prefix, String name, String urn)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.Parse(XmlReader reader)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.XML.CodeDomXmlProcessor.ParseXml(String xmlStream, CodeStatementCollection statementCollection, String fileName, String methodName)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomParser.OnMethodPopulateStatements(Object sender, EventArgs e)
at System.CodeDom.CodeMemberMethod.get_Statements()
at System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
If I ignore the exception, form appears blank with no sign of grid control on it. However I can see the code for the grid in the designer file.
Any pointer on this would be a great help.
I have customized grid for my custom requirements like I have added custom text box n all. I have defined 3 constructors
public GridControl()
public GridControl(IContainer container)
protected GridControl(SerializationInfo info, StreamingContext context)
I have this problem all the time...it sucks.
[Ramble(on)]
Here is what I think I know:
When designing place the control on a form. Build and refresh often..this will let you know what change caused the designer to barf.
Close visual studio all the way an re-open....I cannot tell you how many times I have chased a designer error that was the designer being "stuck".
It is very important that you understand : The designer is really, really stupid...like bag of rocks stupid.
Any public fields or properties of custom object types will almost always cause designer confusion*. I find the following attributes will clear up most of these problems:
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
Public fields or properties without a default constructor will always cause designer confusion. When you drop a user control on a form the designer effectively creates the control..so any public object needs a clear creation path. I have found that the easiest way around this (read hack) is keeping the non-trivial custom classes private and expose public properties as a facade.
-- Did I say restart visual studio because sometimes the designer is "stuck" on an error that doesn't exist ?..I hope I did.
[Ramble(off)]
I hope some of this helps..
*designer confusion: Instead of showing your controls the designer shows you a useless error message that might or might not include the dire warning that it is protecting you from code loss...blah, blah.
It sounds like a NullReferenceException is thrown in your control's default constructor (the one without parameters). Obviously, this exception is only thrown at design time since you say it works at runtime. Do you perform any initialization code in this constructor, like data base calls or similar? Or do you use any instances which might not be available at design time?
It looks like the form-designer is trying to initialize the control. Yet, the property it is trying to initialize may have been removed from the UserControl. There are lots of way to troubleshoot this problem. I recommend you debug the control in design-time. It is the surest way to find the problem. Check out "MSDN Search" for "design-time control debugging" at http://social.msdn.microsoft.com/Search/en-US?query=design-time+control+debugging&ac=8
I had run in to the same error check whether your Windows Form class inherits from System.Windows.Forms.Form class as in Form1:Form Hope dis helps !!!!

How to create a derived ComboBox with pre-bound datasource that is designer friendly?

I'd like to create a derived control from System.Windows.Forms.ComboBox that is bound to a list of objects that I retrieve from the database. Idea is other developers can just drop this control on their form without having to worry about the datasource, binding, unless they want to.
I have tried to extend combobox and then set the DataSource, DisplayMember, and ValueMember in the constructor.
public class CustomComboBox : ComboBox
{
public CustomComboBox()
{
this.DataSource = MyDAL.GetItems(); // Returns List<MyItem>
this.DisplayMember = "Name";
this.ValueMember = "ItemID";
}
}
Works when I run, but throws a lot of errors in Visual Studio's once it's added to any form. The error I get is:
"Code generation for property 'Items' failed. Error was: 'Object reference not set to an instance of an object"
What's the correct way to accomplish this (C#, Winforms, .NET 2.0+)?
The problem is that the designer actually does some compilation and execution in a slightly different context than normally running the program does.
In the constructor, you can wrap your code in:
if (!DesignMode)
{
//Do this stuff
}
That will tell the designer to not run any of your initialization code while it is being designed.
DesignMode property doesn't work in a constructor. From googling for a while, found this LicenseManager thing.
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
{
// Do your database/IO/remote call
}
However LicenseManager only works in constructors. For eventhandlers use DesignMode.
Source: http://dotnetfacts.blogspot.com/2009/01/identifying-run-time-and-design-mode.html
Another reference: http://weblogs.asp.net/fmarguerie/archive/2005/03/23/395658.aspx
My usual comment here - DesignMode is not reliable in any situation other than if the control is placed directly on a design surface - i.e. if the control is placed on another control, DesignMode is not true even if you are in design mode. I have found NO reliable way to tell if you are in design mode - especially with inherited controls. Even variants using Site are not reliable if the control is inherited from a non-visual control (e.g. Common Dialog).
See http://keyofdflat.livejournal.com/5407.html (make sure to read the last comment).

.Net C# Design View errors

I have subclassed a Treeview and on instantiation it loads a new ImageList (and the associated Images).
Whenever I switch to the designer view, it's also trying to run this code, however the images aren't in the designer's path, so it crashes. I ended up putting in a hack to see if the current directory is "Visual Studio", then do nothing... but that's so ugly.
I find this happening for other things. If a control is trying to use objects during load/initalization that are only available while the program is running, then the Design View cannot bring up the control.
But is there a way to get around this?
I guess what I'm hoping for is having a try/catch for the Designer (only) with the ability to ignore a few errors I know will be happening (like FileNotFoundException, etc.).
Thanks
Everything that inherits from System.Windows.Forms.Control has a DesignMode property that returns a boolean indicating if you are in design mode or not. You could use this to determine when to/when not to load external resources.
Usually it is better to move the loading of these resources to an override of OnLoad as they are rarely required directly at construction. This fixes the issue you are seeing and means that only trees which get displayed at least once will perform these additional resource loading steps.
Otherwise, you can just exclude these steps during design time by checking the DesignMode property and acting accordingly.
This is a fine pattern to use if you're making a control library with a sample of images when shown in the designer or hook ins to other designer features but as a pattern for development I'm not sure it's very effective.
I would suggest shifting your "business logic" (in this case your loading of certain images into a treeview) outside of the bounds of your treeview control. In your case I would place the logic within the Load event of the form that the control is inside:
public void Load(object sender, EventArgs e)
{
string path = "c:\somePath\toAwesome\Images";
myFunkyTreeView.AddImages(path);
}
For larger apps I personally think you want to shift the logic even out of the forms themselves, but this is debatable measure as it requires additional plumbing as a trade-off for the flexibility this provides.
Thanks for pointing me in the right directioon guys.
I had tried registering to the OnLoad event, but that event is triggered when the Design View comes up, so that didn't quite work for me (am I doing something wrong?).
Anyway, I looked a bit more into the DesignMode property. It can only work for Controls, and sometimes your object may not even be a control.
So here's the answer I prefer:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) {
// design-time stuff
} else {
// run-time stuff
}
Found it here.

Categories