Hi all,
I am building a control that will report data errors or successful data actions back to the user and have run into a problem and am stuck. Bascially, the control uses a layout template to allow the UI developer to specify how to display errors:
<cc1:DataReporter ID="DataErrorReporter1" runat="server">
<ErrorLayoutTemplate>
<h2><asp:Literal ID="ErrorHeaderText" runat="server" /></h2>
<ol>
<asp:PlaceHolder ID="errorItemPlaceHolder" runat="server" />
</ol>
<h2><asp:Literal ID="ErrorActionText" runat="server" /></h2>
</ErrorLayoutTemplate>
<ErrorItemTemplate>
<li><asp:Literal ID="ErrorMessage" runat="server" /></li>
</ErrorItemTemplate>
</cc1:DataReporter>
The problem is that i cannot get the control to output the ErrorItemTemplate contents in the errorItemPlaceholder and that i am also seeing some spurious span tags being output:
<span id="DataErrorReporter1"><span>
<h2></h2>
<ol>
</ol>
<h2></h2>
<span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span><span>
<li></li>
</span></span></span>
The code for the control is as follows:
Public Class DataReporter
Inherits WebControl
Implements INamingContainer
Private _errorLayoutTemplate As ITemplate
Private _errorItemTemplate As ITemplate
Private _dataErrorException As DataErrorException
<System.ComponentModel.Browsable(True), _
System.ComponentModel.Description("The error objects template."), _
TemplateContainer(GetType(DataReporterLayoutContainer)), _
PersistenceMode(PersistenceMode.InnerProperty)> _
Public Overridable Property ErrorLayoutTemplate() As ITemplate
Get
Return Me._errorLayoutTemplate
End Get
Set(ByVal value As ITemplate)
Me._errorLayoutTemplate = value
End Set
End Property
<System.ComponentModel.Browsable(True), _
System.ComponentModel.Description("The error item template."), _
TemplateContainer(GetType(DataReporterErrorItem)), _
PersistenceMode(PersistenceMode.InnerProperty)> _
Public Overridable Property ErrorItemTemplate() As ITemplate
Get
Return Me._errorItemTemplate
End Get
Set(ByVal value As ITemplate)
Me._errorItemTemplate = value
End Set
End Property
<System.ComponentModel.Bindable(True), _
System.ComponentModel.Category("Appearance")> _
Public Property DataErrorException() As DataErrorException
Get
Return Me._dataErrorException
End Get
Set(ByVal value As DataErrorException)
Me._dataErrorException = value
End Set
End Property
<System.ComponentModel.Bindable(True), _
System.ComponentModel.Category("Appearance"), _
System.ComponentModel.DefaultValue("")> _
Public Property ErrorHeaderText() As String
Get
Dim o As Object = Me.ViewState("DataErrorReporterStateErrorHeaderText")
If (o Is Nothing) Then
Return String.Empty
End If
Return DirectCast(o, String)
End Get
Set(ByVal value As String)
Me.ViewState("DataErrorReporterStateErrorHeaderText") = value
End Set
End Property
<System.ComponentModel.Bindable(True), _
System.ComponentModel.Category("Appearance"), _
System.ComponentModel.DefaultValue("")> _
Public Property ErrorActionText() As String
Get
Dim o As Object = Me.ViewState("DataErrorReporterStateErrorActionText")
If (o Is Nothing) Then
Return String.Empty
End If
Return DirectCast(o, String)
End Get
Set(ByVal value As String)
Me.ViewState("DataErrorReporterStateErrorActionText") = value
End Set
End Property
<System.ComponentModel.DefaultValue("itemPlaceholder"), _
System.ComponentModel.Category("Behavior")> _
Public Overridable Property ErrorItemPlaceholderID() As String
Get
Dim o As Object = Me.ViewState.Item("ErrorItemPlaceholderID")
If (Not o Is Nothing) Then
Return DirectCast(o, String)
End If
Return "errorItemPlaceholder"
End Get
Set(ByVal value As String)
Me.ViewState.Item("ErrorItemPlaceholderID") = value
End Set
End Property
Public Overrides ReadOnly Property Controls() As ControlCollection
Get
Me.EnsureChildControls()
Return MyBase.Controls
End Get
End Property
Protected Overrides Sub CreateChildControls()
Me.Controls.Clear()
Me.CreateItems()
End Sub
Public Overrides Sub DataBind()
Me.CreateChildControls()
Me.ChildControlsCreated = True
MyBase.DataBind()
End Sub
Private Function GetPlaceholderContainer() As Control
Dim control As Control = Me.Controls(0).FindControl(Me.ErrorItemPlaceholderID)
Dim parent As Control = control.Parent
parent.Controls.Remove(control)
Return parent
End Function
Private Sub CreateItems()
Dim container As New DataReporterLayoutContainer
Me.ErrorLayoutTemplate.InstantiateIn(container)
Me.Controls.Add(container)
Dim placeHolderContainer As Control = Me.GetPlaceholderContainer()
Dim dataErrors As New ArrayList
For Each dei As IDataErrorInfo In Me._dataErrorException.DataErrorObjects
dataErrors.Add(dei.Error)
Next
For Each s As String In dataErrors
Dim item As New DataReporterErrorItem(s)
Me._errorItemTemplate.InstantiateIn(item)
placeHolderContainer.Controls.Add(item)
Next
End Sub
End Class
Friend Class DataReporterErrorItem
Inherits WebControl
Implements INamingContainer
Private _dataError As String
Public ReadOnly Property DataError() As String
Get
Return Me._dataError
End Get
End Property
Friend Sub New(ByVal dataError As String)
Me._dataError = dataError
End Sub
End Class
Friend Class DataReporterLayoutContainer
Inherits WebControl
Implements INamingContainer
End Class
Can any of you guys point out where I'm going wrong? The action takes place in the CreateItems method. It basically instantiates the ErrorLayoutTemplate, gets the errorItemPlaceholder and attempts to add the errors to this. Any help you have to offer would be greatly appreciated!
Regards,
Stephen