views:

1536

answers:

6

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!

+1  A: 

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?

Glenn Slaven
A: 

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.

KMessenger
A: 

Thank you for the responses. I checked my code and am attaching it here. Like Glenn mentioned, there is database call but nothing is happening till one method (BeginInterview) is called from the parent page.

I included the parameterless constructor and tried it as well.

Below is my code: Stripped some of the render and create child controls for readability sake.

[ToolboxData("<{0}:ServerControl1 runat=server>")] public class ServerControl1 : CompositeControl, INamingContainer { public ServerControl1() {

    }

    protected override void OnInit(EventArgs e)
    {
            if (Page.IsPostBack)
            {
                if (HttpContext.Current.Session["controlCollection"] != null)
                {
                    foreach (Control c in ControlCollection)
                    {
                        Controls.Add(c);
                    }
                }
            }
            base.OnInit(e);
    }


    protected override void OnPreRender(EventArgs e)
    {
        HtmlLink cssLink = new HtmlLink();
        cssLink.ID = "ControlStyleSheet.css";
        cssLink.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(),  "IWC.CustomControl.Resources.ControlStyleSheet.css");
        cssLink.Attributes.Add("rel", "stylesheet");
        cssLink.Attributes.Add("type", "text/css");
        HtmlLink cssLink2 = new HtmlLink(); ;

        if (CSSPath != string.Empty || CSSPath != null)
        {
            cssLink2.ID = "customStyleSheet.css";
            cssLink2.Href = CSSPath;
            cssLink2.Attributes.Add("rel", "stylesheet");
            cssLink2.Attributes.Add("type", "text/css");
        }

        bool CssLinkAlreadyExists = false;
        foreach (Control headctrl in Page.Header.Controls)
        {
            if (headctrl.ID == cssLink.ID)
            {
                CssLinkAlreadyExists = true;
                break;
            }
        }
        if (!CssLinkAlreadyExists)
        {
            Page.Header.Controls.AddAt(0, cssLink);
        }
       base.OnPreRender(e);
    }


    protected override void CreateChildControls()
    {
            panelDropShadow.ID = "panelDropShadow";

            panelBackgrnd.ID = "panelBackgrnd";

            rightButton.ID = "rightButton";
            rightButton.Click += new ImageClickEventHandler(rightButton_Click);

            leftButton.ID = "leftButton";
            leftButton.Click += new ImageClickEventHandler(leftButton_Click);

            imgFinish.ID = "imgFinish";
            imgFinish.Click += new ImageClickEventHandler(imgFinish_Click);
            imgFinish.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "IWC.CustomControl.Resources.Images.finish_button_v2.jpg");

            lbError.ID = "lbError";
            string htmlColor = "#c00000";
            lbError.ForeColor = System.Drawing.ColorTranslator.FromHtml(htmlColor);

            lbMain.ID = "lbMain ";

            imgError.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "IWC.CustomControl.Resources.Images.alert_icon.gif");
            imgError.CssClass = "IWC_imgError";

            lb_Close.Text = "Close";
            lb_Close.ID = "lb_Close";
            lb_Close.CssClass = "IWC_lbClose IWC_grid-element-green";
            lb_Close.Click += new EventHandler(lb_Close_Click);

            Controls.Add(panelDropShadow);
            Controls.Add(panelBackgrnd);

            Controls.Add(leftButton);
            Controls.Add(rightButton);

            Controls.Add(lbMain);

            Controls.Add(imgError);
            Controls.Add(lbError);


            Controls.Add(lb_Close);

            Controls.Add(imgFinish);

            if (HttpContext.Current.Session["controlCollection"] != null)
            {
                ControlCollection.Clear();
                ControlCollection = (List<Control>)HttpContext.Current.Session["controlCollection"];
                foreach (Control c in ControlCollection)
                {
                    Controls.Add(c);
                }
            }
    }

protected override void RenderContents(HtmlTextWriter writer) {

            panelDropShadow.RenderControl(writer);
            panelBackgrnd.RenderBeginTag(writer);
            lbMain.RenderControl(writer);
            leftButton.RenderControl(writer);
            rightButton.RenderControl(writer);

            lbError.RenderControl(writer);
            imgError.RenderControl(writer);
            imgFinish.RenderControl(writer);
            lb_Close.RenderControl(writer);

           foreach (Control c in ControlCollection)
           {
             c.RenderControl(writer);
           }

    panelBackgrnd.RenderEndTag(writer);
    }

public void BeginInterview(string SessionID, string UserID, int ScriptID, int ValidLength) { ctrl = (MyService)HttpContext.Current.Session["ctrl"]; StartScript(ScriptID, SessionID, UserID, ValidLength); } }

your time and help is much appreciated.

A: 

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 Slaven
A: 

Glenn, Thank you for the response. Page != null didnt help much. Same error... Kind of in a state to give up :(

A: 

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