views:

659

answers:

1

Folks,

I am having a devil of a time with a custom control. The control is very simple - it just displays a list of "StepItems" (rendered as table rows), each with an icon. When I first drag it onto a page, and add StepItems to its collection, it renders perfectly. If I provide some text for its Header property, that also renders perfectly.

If I then look at the HTML source view, and then back to the design view, I get an error where my control should be. There are two kinds of errors:

  • If I set the .Header property, the error reads "StepProgressControl1:'someheadertext' could not be set on property 'Header'.

  • If I don't set the .Header, but add StepItems to the collection, I get this: "ErrorStepProgressControl1:'StepItems' could not be initialized. Details: Method not found: 'System.Collections.Generic.List`1 StepProgressControl.TKC.Experiment.StepProgressControl.get_StepItems()'."

The complete code for my custom control is below. If you can provide any help, thank you a great deal!

  • Tom

'================================

Imports System Imports System.Collections Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Security.Permissions Imports System.ComponentModel

Namespace TKC.Experiment

' THIS IS THE INTERNAL "CHILD" ELEMENT
< _
    PersistenceMode(PersistenceMode.InnerProperty), _
    TypeConverter(GetType(StepItemConverter)) _
   > _
Public Class StepItem

    Private _name As String

    Public Sub New()
        Me.New("")
    End Sub


    Public Sub New(ByVal name As String)
        Me._name = name
    End Sub

    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
End Class

'=====================================================================

' THIS IS THE ACTUAL "PARENT" WEB CONTROL
< _
   ParseChildren(True, "StepItems"), _
   PersistChildren(False) _
> _
Public NotInheritable Class StepProgressControl
    Inherits WebControl


    Private _header As String = String.Empty
    Private _stepItems As New List(Of StepItem)

    Public Sub New()
        Me.Header = "StepProgressControl"
    End Sub



    < _
        PersistenceMode(PersistenceMode.Attribute) _
    > _
    Public Property Header() As String
        Get
            Return _header
        End Get
        Set(ByVal value As String)
            _header = value
        End Set
    End Property


    < _
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
        PersistenceMode(PersistenceMode.InnerProperty) _
    > _
    Public ReadOnly Property StepItems() As List(Of StepItem)
        Get
            If _stepItems Is Nothing Then
                _stepItems = New List(Of StepItem)
            End If
            Return _stepItems
        End Get
        'Set(ByVal value As List(of stepitem))
        '    _stepItems = value
        'End Set
    End Property


    Public Overrides Sub RenderControl(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.RenderControl(writer)

        Dim label As New Label()
        label.Text = Header

        label.RenderControl(writer)

        Dim table As New Table()
        Dim htr As New TableRow()

        Dim hcell1 As New TableHeaderCell()
        hcell1.Text = "Name"
        htr.Cells.Add(hcell1)

        Dim hcell2 As New TableHeaderCell()
        hcell2.Text = "Title"
        htr.Cells.Add(hcell2)


        table.BorderWidth = Unit.Pixel(0)

        Dim stepItem As StepItem

        For Each stepItem In StepItems
            Dim tr As New TableRow()

            Dim cell1 As New TableCell()
            Dim img As New HtmlImage
            img.Src = ""
            img.Alt = ""
            cell1.Controls.Add(img)
            tr.Cells.Add(cell1)

            Dim cell2 As New TableCell()
            cell2.Text = stepItem.Name
            tr.Cells.Add(cell2)

            table.Rows.Add(tr)
        Next stepItem

        table.RenderControl(writer)


    End Sub

End Class


'========================================

'THIS IS A "TYPE CONVERTER" - JUST A COSMETIC THING, NOT CAUSING TROUBLE...
Public Class StepItemConverter
    Inherits TypeConverter
    Public Overloads Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
        Dim obj As StepItem = DirectCast(value, StepItem)
        Return obj.Name
    End Function
End Class

End Namespace

A: 

You will want to implement your own Collection object to represent the list - otherwise the designer will not display it properly.

See the ICollection, IEnumerable, etc. interfaces.

Fritz H