ASP.NET Data Bound UserControl

The .NET 2.0 provides   System.Web.UI.WebControls.BaseDataBoundControl  and  DataBoundControl classes that can be useful for Custom Data-Bound Web Server Controls  . However it often convinient to have User Control with similar data-binding capabilities.
Unfortunetely .Net doesn’t allow multiple inheritance, so I have to duplicate the functionality in my DataBoundUserControl class derived from UserControl class.  

At the moment the DataBoundUserControl class is not fully implemented.As it explained in “Data Source Controls – Under the Hood” , data-bound control has to use a wrapper class in order to expose the DataSource as a data source control (ReadOnlyDataSource that implements IDataSource, returning a view (ReadOnlyDataSourceView) that only supports the select method). MS made ReadOnlyDataSource and ReadOnlyDataSourceView not public, so we need to re-invent them if needed.
As a shortcut derived User Controls should overide PerformSelectDataBinding() 
method.

Imports Microsoft.VisualBasic

Imports System.ComponentModel

‘Based on http://msdn2.microsoft.com/en-us/library/ms366539.aspx article “Developing Custom Data-Bound Web Server Controls for ASP.NET 2.0”

Public Class DataBoundUserControl

    Inherits System.Web.UI.UserControl

    True), DefaultValue(CStr(Nothing))> _

    Public Overridable Property DataSource() As Object

        ‘from http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.basedataboundcontrol.datasource.aspx

        ‘ When you set the DataSource property, the ValidateDataSource method is called. In addition, if the data-bound control has already been initialized, the OnDataPropertyChanged method is called to set the RequiresDataBinding property to true.

        Get

            Return m_dataSource

        End Get

        Set(ByVal value As Object)

            If (Not value Is Nothing) Then

                ValidateDataSource(value)

            End If

            m_dataSource = value

            OnDataPropertyChanged()

        End Set

    End Property

    Private m_dataSource As Object

 

    Public Overridable Property DataSourceID() As String

        Get

            Dim o As Object = ViewState(“DataSourceID”)

            If (Not o Is Nothing) Then

                Return CStr(o)

            End If

            Return String.Empty

        End Get

        Set(ByVal value As String)

            ViewState.Item(“DataSourceID”) = value

            OnDataPropertyChanged()

        End Set

    End Property

    Protected Property RequiresDataBinding() As Boolean

        Get

            Return m_requiresDataBinding

        End Get

        Set(ByVal value As Boolean)

            m_requiresDataBinding = value

            If (m_preRendered AndAlso m_requiresDataBinding = True) Then

                Me.EnsureDataBound()

            Else

            End If

        End Set

    End Property

    Private m_requiresDataBinding As Boolean

    Protected Overridable Sub ValidateDataSource( _

    ByVal dataSource As Object _

    )

        ‘from ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref16/html/M_System_Web_UI_WebControls_DataBoundControl_ValidateDataSource_1_b4c5a2da.htm

        ‘The DataBoundControl class checks the type of the object that is set for the DataSource property to ensure that it is an instance of the IDataSource, IListSource, or IEnumerable interface.

        If (((Not dataSource Is Nothing) AndAlso Not TypeOf dataSource Is IListSource) AndAlso (Not TypeOf dataSource Is IEnumerable AndAlso Not TypeOf dataSource Is IDataSource)) Then

            Throw New InvalidOperationException(“DataBoundControl Invalid DataSource Type” & dataSource.GetType.ToString())

        End If

 

    End Sub

    Protected Overridable Sub OnDataPropertyChanged()

        RequiresDataBinding = True

    End Sub

 

 

    ‘Calls the DataBind method if the DataSourceID property is set and the data-bound control is marked to require binding.

    ‘Does nothing if DataSource is used

    ‘The EnsureDataBound method is called during the OnPreRender method, to call the DataBind method if the data-bound control is not yet bound.

    ‘The EnsureDataBound method might also be called during calls to CreateChildControls and LoadPostData methods.(?? -not tested yet)

    Protected Overridable Sub EnsureDataBound()

        If (RequiresDataBinding And IsBoundUsingDataSourceID()) Then

            Me.DataBind()

        End If

     End Sub

    ‘Overrides the Control.OnPreRender event handler to call EnsureDataBound before calling the base class OnPreRender method.

    ‘invokes data-binding logic as late as possible during the page life cycle and only when needed

    Protected Overrides Sub OnPreRender(ByVal e As EventArgs)

        m_preRendered = True

        EnsureDataBound()

        MyBase.OnPreRender(e)

        m_preRendered = False

    End Sub

    Private m_preRendered As Boolean = False

    Protected ReadOnly Property IsBoundUsingDataSourceID() As Boolean

        Get

            Return (DataSourceID.Length > 0)

        End Get

    End Property

    Public Overrides Sub DataBind()

        PerformSelect()

    End Sub

    Protected Sub MarkAsDataBound()

        ViewState(“DataBound”) = True

    End Sub

 

    Protected Overridable Sub PerformSelect()

 

        ‘ Call OnDataBinding here if bound to a data source using the DataSource property (instead of a DataSourceID) because the

        ‘ data-binding statement is evaluated before the call to GetData.

        If Not IsBoundUsingDataSourceID Then

            OnDataBinding(EventArgs.Empty)

        End If

 

        PerformSelectDataBinding()

        ‘ The PerformDataBinding method has completed.

        RequiresDataBinding = False

        MarkAsDataBound()

 

        ‘ Raise the DataBound event.

        ‘Not implemented yet OnDataBound(EventArgs.Empty)

    End Sub ‘PerformSelect

 

    Protected Overridable Sub PerformSelectDataBinding()

        Throw New NotImplementedException(” should be overridde in derived class”)

        ” The GetData method retrieves the DataSourceView object from the

        ” IDataSource associated with the data-bound control.

        ‘TODO  according to http://www.manuelabadia.com/blog/PermaLink,guid,678ed6d8-dce8-40d7-9117-0ffd016fe886.aspx

        ‘it has to use a wrapper class in order to expose the DataSource as a data source control (ReadOnlyDataSource that implements IDataSource, returning a view (ReadOnlyDataSourceView) that only supports the select method).

        ‘Unfortunately, MS made ReadOnlyDataSource and ReadOnlyDataSourceView not public, so we need to re-crete them if needed

        ‘GetData().Select(CreateDataSourceSelectArguments(),  AddressOf OnDataSourceViewSelectCallback)

    End Sub ‘PerformSelect

End Class

 

 

Advertisements