Wednesday, July 20, 2005

В проекте возникла проблема: имеется куча бизнес-объектов, которые необходимо как-то отображать/редактировать/обновлять/добавлять. Возник вопрос как лучше всего организовать web-приложение в этом случае, чтобы писать по минимуму рутинного кода для привязки объекта к контролам.

Все решилось просто, главная идея - чтобы идентификаторы контролов совпадали с названиями свойств.

 

Наш тестовый бизнес-объект:

 

Public Class TestBusinessObject

Private _id As String

Private _name As String

Private _city As String

Private _hasSomething As Boolean

 

Public Property Id() As String

Get

Return _id

End Get

Set(ByVal Value As String)

_id = Value

End Set

End Property

 

Public Property Name() As String

Get

Return _name

End Get

Set(ByVal Value As String)

_name = Value

End Set

End Property

 

Public Property City() As String

Get

Return _city

End Get

Set(ByVal Value As String)

_city = Value

End Set

End Property

 

Public Property HasSomething() As Boolean

Get

Return _hasSomething

End Get

Set(ByVal Value As Boolean)

_hasSomething = Value

End Set

End Property

End Class

 

Наш класс-помощник в деле bindinga (привязки данных):

 

Imports System.Reflection

 

Public Class BindingHelper

 

#Region "Binding object to controls"

 

    '''

    ''' This will bind object properties to control values

    '''

    ''' Object

    ''' Container (page usually)

    ''' Prefix of control name (this will be used if you need to bind several controls to the same page)

    Public Shared Sub BindObjectToControls(ByVal obj As Object, ByVal container As Control, ByVal propertyNamePrefix As String)

        'check object for nothing

        If obj Is Nothing Then

            Return

        End If

 

        'loop all obj properties

        For Each objProperty As PropertyInfo In obj.GetType.GetProperties()

            'look for control with specified property name

            Dim control As control = container.FindControl(propertyNamePrefix & objProperty.Name)

 

            If Not (control Is Nothing) Then

                SetPropertyValueToControl(control, objProperty.GetValue(obj, Nothing))

            End If

        Next

    End Sub

 

    '''

    ''' This will bind object properties to control values

    '''

    ''' Object

    ''' Container (page usually)

    Public Shared Sub BindObjectToControls(ByVal obj As Object, ByVal container As Control)

        BindObjectToControls(obj, container, String.Empty)

    End Sub

 

    'Bind property value to control

    Private Shared Sub SetPropertyValueToControl(ByVal control As Control, ByVal value As Object)

        If TypeOf control Is TextBox Then

            'process text box

            CType(control, TextBox).Text = value

 

        ElseIf TypeOf control Is DropDownList Then

            'process DropDownList

            Dim ddList As DropDownList = CType(control, DropDownList)

            Dim item As ListItem = ddList.Items.FindByValue(value)

 

            If item Is Nothing Then

                ddList.SelectedIndex = 0

            Else

                ddList.SelectedIndex = ddList.Items.IndexOf(item)

            End If

 

        ElseIf TypeOf control Is CheckBox Then

            'process CheckBox

            CType(control, CheckBox).Checked = value

 

        ElseIf TypeOf control Is HtmlInputHidden Then

            'process HtmlInputHidden

            CType(control, HtmlInputHidden).Value = value

 

        End If

    End Sub

 

#End Region

 

#Region "Binding controls to object"

 

    '''

    ''' This will bind control values to object properties

    '''

    ''' Object

    ''' Container (page usually)

    ''' Prefix of control name (this will be used if you need to bind several controls to the same page)

    Public Shared Sub BindControlsToObject(ByVal obj As Object, ByVal container As Control, ByVal propertyNamePrefix As String)

        'check object for nothing

        If obj Is Nothing Then

            Return

        End If

 

        'loop all obj properties

        For Each objProperty As PropertyInfo In obj.GetType.GetProperties()

            'look for control with specified property name

            Dim control As control = container.FindControl(propertyNamePrefix & objProperty.Name)

 

            If Not (control Is Nothing) Then

                objProperty.SetValue(obj, GetControlValue(control), Nothing)

            End If

        Next

    End Sub

 

    '''

    ''' This will bind control values to object properties

    '''

    ''' Object

    ''' Container (page usually)

    Public Shared Sub BindControlsToObject(ByVal obj As Object, ByVal container As Control)

        BindControlsToObject(obj, container, String.Empty)

    End Sub

 

    'Bind property value to control

    Private Shared Function GetControlValue(ByVal control As Control) As Object

        If TypeOf control Is TextBox Then

            'process text box

            Return CType(control, TextBox).Text

 

        ElseIf TypeOf control Is DropDownList Then

            'process DropDownList

            Return CType(control, DropDownList).SelectedValue

 

        ElseIf TypeOf control Is CheckBox Then

            'process CheckBox

            Return CType(control, CheckBox).Checked

 

        ElseIf TypeOf control Is HtmlInputHidden Then

            'process HtmlInputHidden

            Return CType(control, HtmlInputHidden).Value

 

        End If

    End Function

 

#End Region

 

End Class

 

Привязка в одну сторону (из объекта в контролы):

 

Dim testObject As New TestBusinessObject

testObject.Id = Guid.NewGuid().ToString

testObject.Name = "name"

testObject.City = "NY"

testObject.HasSomething = True

 

BindingHelper.BindObjectToControls(testObject, Page, "obj1_")

 

Привязка в другую сторону (из контрола в объект):

 

Dim testObject As New TestBusinessObject

BindingHelper.BindControlsToObject(testObject, Page, "obj1_")

 

Данная реализация имеет два ограничения:

1) названия контролов (их идентификаторы) должны совпадать с названиями свойств. Либо если мы используем префикс, то должны быть в формате ПРЕФИКСИМЯСВОЙСТВА, например obj1_Id;

2) сейчас обрабатываются только контролы типа TextBox, DropDownList, CheckBox и HtmlInputHidden, но это легко расширяется вами (возможно, вам понадобится поддержка Calendar или чего-то в этом духе).

 

Удобства: мы избегаем рутинной работы по заполнению соответствий между свойствами объекта и контролами в обе стороны - когда хотим отобразить объект или после PostBack.

posted @ 6:00 PM | Feedback (4)
 

На просторах интернета случайно наткнулся на интересное расширение для NUnit: http://nunitasp.sourceforge.net/

Смысл его в том, чтобы проверять ASP.NET страницы на правильное заполнение и т.п. Все предельно просто, так что рекомендую воспользоваться!

posted @ 5:55 PM | Feedback (0)