I am creating a templated control. Only Single instance of Template is expected in the control. If I place any control inside template and try to access its property in PageLoad event, it gives an error - "Object not set to an instance of an object." However,
if I try to access the same control(which is present inside ITemplate) property in any event, it works fine returning the correct values.
Code for control, ASPX & code-behind is as follows:
Control Code
Namespace MyNS
<AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level:=AspNetHostingPermissionLevel.Minimal), _
ToolboxItem(False)> _
Public Class GenericTemplateOwner
Inherits Control
Implements INamingContainer
End Class
<AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level:=AspNetHostingPermissionLevel.Minimal), _
ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>"), _
ParseChildren(True), PersistChildren(False)> _
Public Class MyControl
Inherits Control
Implements INamingContainer
Private _template As ITemplate
Private _owner As GenericTemplateOwner
<Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public ReadOnly Property ContentTemplateOwner() As GenericTemplateOwner
Get
EnsureChildControls()
Return _owner
End Get
End Property
<Browsable(False), PersistenceMode(PersistenceMode.InnerProperty), DefaultValue(GetType(ITemplate), ""), _
TemplateInstance(TemplateInstance.Single), Description("Control template"), _
TemplateContainer(GetType(GenericTemplateOwner)), RefreshProperties(RefreshProperties.All)> _
Public Overridable Property Content() As ITemplate
Get
Return _template
End Get
Set(ByVal value As ITemplate)
_template = value
End Set
End Property
Protected Overrides Sub CreateChildControls()
Me.Controls.Clear()
'Rendering the content of the Template
_owner = New GenericTemplateOwner()
If (Not Me.Content Is Nothing) Then
Me.Content.InstantiateIn(Me.ContentTemplateOwner)
End If
Me.Controls.Add(Me.ContentTemplateOwner)
End Sub
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
If (Not Me.Page Is Nothing) Then
Me.Page.VerifyRenderingInServerForm(Me)
End If
Dim tStr As New StringBuilder()
tStr.Append("<div id=""" & Me.ClientID & """ class=""MyControl"">")
writer.Write(tStr.ToString())
MyBase.Render(writer)
writer.Write("</div>")
End Sub
End Class
End Namespace
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
'Works fine here
Dim str As String = Button1.Text
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Gives an Exception - "Object reference not set to an instance of an object."
Dim str As String = Button1.Text
End Sub
End Class
ankur.nigam
Member
536 Points
141 Posts
Controls present inside ITemplate gives error when accessed in PageLoad event
Sep 05, 2011 12:56 PM|LINK
Hello,
I am creating a templated control. Only Single instance of Template is expected in the control. If I place any control inside template and try to access its property in PageLoad event, it gives an error - "Object not set to an instance of an object." However, if I try to access the same control(which is present inside ITemplate) property in any event, it works fine returning the correct values.
Code for control, ASPX & code-behind is as follows:
Control Code
Namespace MyNS <AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal), _ AspNetHostingPermission(SecurityAction.InheritanceDemand, Level:=AspNetHostingPermissionLevel.Minimal), _ ToolboxItem(False)> _ Public Class GenericTemplateOwner Inherits Control Implements INamingContainer End Class <AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal), _ AspNetHostingPermission(SecurityAction.InheritanceDemand, Level:=AspNetHostingPermissionLevel.Minimal), _ ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>"), _ ParseChildren(True), PersistChildren(False)> _ Public Class MyControl Inherits Control Implements INamingContainer Private _template As ITemplate Private _owner As GenericTemplateOwner <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _ Public ReadOnly Property ContentTemplateOwner() As GenericTemplateOwner Get EnsureChildControls() Return _owner End Get End Property <Browsable(False), PersistenceMode(PersistenceMode.InnerProperty), DefaultValue(GetType(ITemplate), ""), _ TemplateInstance(TemplateInstance.Single), Description("Control template"), _ TemplateContainer(GetType(GenericTemplateOwner)), RefreshProperties(RefreshProperties.All)> _ Public Overridable Property Content() As ITemplate Get Return _template End Get Set(ByVal value As ITemplate) _template = value End Set End Property Protected Overrides Sub CreateChildControls() Me.Controls.Clear() 'Rendering the content of the Template _owner = New GenericTemplateOwner() If (Not Me.Content Is Nothing) Then Me.Content.InstantiateIn(Me.ContentTemplateOwner) End If Me.Controls.Add(Me.ContentTemplateOwner) End Sub Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) If (Not Me.Page Is Nothing) Then Me.Page.VerifyRenderingInServerForm(Me) End If Dim tStr As New StringBuilder() tStr.Append("<div id=""" & Me.ClientID & """ class=""MyControl"">") writer.Write(tStr.ToString()) MyBase.Render(writer) writer.Write("</div>") End Sub End Class End NamespaceASPX Code
<form id="form1" runat="server"> <div> <cc1:MyControl ID="MyControl1" runat="server"> <Content> <asp:Button ID="Button1" runat="server" Text="Button" /> </Content> </cc1:MyControl> </div> </form>Code-Behind Code
Partial Class _Default Inherits System.Web.UI.Page Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click 'Works fine here Dim str As String = Button1.Text End Sub Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 'Gives an Exception - "Object reference not set to an instance of an object." Dim str As String = Button1.Text End Sub End ClassKindly suggest a workaround.
Ankur
My Blogs:
Twitter | DevAstrum
Decker Dong ...
All-Star
118619 Points
18779 Posts
Re: Controls present inside ITemplate gives error when accessed in PageLoad event
Sep 07, 2011 01:51 AM|LINK
Hello,
The reason is that CreateChildrenControls won't be automatically called, And you should change your codes like:
ankur.nigam
Member
536 Points
141 Posts
Re: Controls present inside ITemplate gives error when accessed in PageLoad event
Sep 09, 2011 04:52 AM|LINK
Thanks Decker.
You suggestion worked. So, in the control code, I override OnInit() and put EnsureChildControls() in it. Now control always works like a charm.
You rock.
Ankur
My Blogs:
Twitter | DevAstrum