views:

495

answers:

3

I've got an issue with nested controls not loading properly. I've tried various page methods and nothing seems to work.

EDIT: The site compiles and runs fine--it just leaves a blank screen though.

Basically I have a wrapper control for a Chart that allows me to select data, bind, and customize the chart with a lot of abstraction. I need another wrapper control for that because there may be groups of charts that I want to represent easily.

Generalized answers would be great too.

Here's what I have. I've replaced my custom properties/attributes with fillers:

Default.aspx:

<%@ Page Language="C#" CodeBehind="Default.aspx.cs" %>
<%@ Register src="OuterUserControl.ascx" tagname="OuterUserControl" tagprefix="uc2" %>
<uc2:OuterUserControl ID="uc1" runat="server" Att1="foo" Att2="bar" />

OuterUserControl.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OuterUserControl.ascx.cs" Inherits="Proj.OuterUserControl" EnableViewState="false" %>
<%@ Register src="InnerUserControl.ascx" tagname="InnerUserControl" tagprefix="uc1" %>
<div runat="server" id="holder"></div>

OuterUserControl.ascx.cs:

private member variables
Att1
Att2
protected void Page_Load(object sender, EventArgs e)
{
for(int i=0;i<5;i++)
 {
  InnerUserControl cuc = new InnerUserControl(id);
  holder.Controls.Add(cuc);
 }
}

InnerUserControl.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="InnerUserControl.ascx.cs" Inherits="Proj.InnerUserControl" %>
<asp:Chart ID="chart" runat="server"></asp:Chart>

InnerUserControl.ascx.cs:

private int id;
//private member variables
public InnerUserControl(int id)
{
this.id = id;
this.chart = new Chart();
}
protected void Page_Load(object sender, EventArgs e)
{
//Get data for given id
//Databind chart
//etc..
}
A: 

Have you tried adding

<%@ Reference Control="InnerUserControl.ascx" %>

to OuterUserControl.ascx

Slim
Thanks, yes, I have.
Chet
Then try this <%@ Reference Control="InnerUserControl.ascx" %> in OuterUserControl.ascx
Slim
I don't think you did
Slim
@Slim, Thanks, but I have 'Reference's and 'Register's in all the controls and pages...same result of a white page.
Chet
A: 

I'd recommend a different approach. Instead of instantiating the control object in the code-behind and adding it to the controls collection (which I think you'd probably need LoadControl() to do properly and do it earlier than page_load to hook it into the page lifecycle), add the inner control declaratively in the OuterUserControl.

If you need to add the InnerUserControl 5 times (like the example) declare the InnerUseControl inside a repeater. That is bound to the list of id's.

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OuterUserControl.ascx.cs" Inherits="Proj.OuterUserControl" EnableViewState="false" %>
<%@ Register src="InnerUserControl.ascx" tagname="InnerUserControl" tagprefix="uc1" %>
       <asp:Repeater ID="Repeater1" runat="server" DataSourceID="src">
    <ItemTemplate>
      <uc1:InnerUserControl id="iuc" runat="server" ID='<%#Eval("ID")%>'/>
    </ItemTemplate>
    </asp:Repeater>

    <asp:ObjectDataSource ID="src" runat="server" SelectMethod="IDList" 
        TypeName="Web.Default"></asp:ObjectDataSource>
JNappi
+1  A: 

When you add a user control from the code behind, you have to actually load the control. You can do this by doing something like this:

protected void Page_Load(object sender, EventArgs e)
{
    for(int i=0;i<5;i++)
    {
        InnerUserControl cuc = (InnerUserControl)this.Page.LoadControl("InnerUserControl.ascx");

        holder.Controls.Add(cuc);
    }
 }

Assuming they are in the same directory. If not, put the virtual path as the parameter to the LoadControl method. You don't need to have the register statement on the outer control when you do this. Also, I usually use an on the code front instead of a div tag. I'm not sure if this makes a difference, however. I would also recommend loading the control OnInit, as this will ensure all phases of the Lifecycle run for your user controls.

Good Luck!

Nutzy