Solved

Problems with OnItemUpdating for DetailsView

Posted on 2009-05-14
1
581 Views
Last Modified: 2012-05-07
My issue is similar to http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_23004459.html, but in my case I'm dynamically adding TemplateFields to the DetailsView instead of simple BoundFields.

I'm still working with TextBox controls for now, but when I get this to work I need to be able to use this mechanism with other webcontrols like DropDownList etc. as well.

The textboxes show up fine in the detailsview and display the value from the datasource (= a datatable). But when capturing the newly entered values in OnItemUpdating, the Fields collection is empty and so are e.Keys and e.NewValues .
Partial Public Class wsExtendedDetailsView

    Inherits System.Web.UI.WebControls.DetailsView

 

    Private _oSystem As New wsSystem

    Private _oDP As New wsDataProvider

 

#Region "Overrides"

 

    Protected Overrides Sub OnItemCreated(ByVal e As System.EventArgs)

 

        'Be sure to call the base class's OnItemCreated method!

        MyBase.OnItemCreated(e)

 

        If Me.Rows.Count > 0 Then

            ' swap each header <td> cell for a <th> cell

            For Each l_oRow As DetailsViewRow In Me.Rows

                If l_oRow.RowType = DataControlRowType.DataRow Then

                    Dim l_oTD As DataControlFieldCell = l_oRow.Cells(0)

                    If l_oTD.Controls.Count = 0 Then

                        Dim l_oTH As DataControlFieldHeaderCell = New DataControlFieldHeaderCell(l_oTD.ContainingField)

                        l_oTH.Text = l_oTD.Text

                        l_oTH.Attributes.Add("scope", "row")

 

                        ' add the new th and remove the old td

                        l_oRow.Cells.RemoveAt(0)

                        l_oRow.Cells.AddAt(0, l_oTH)

                    End If

                End If

            Next

        End If

 

    End Sub

 

    Protected Overrides Function CreateFieldSet(ByVal dataItem As Object, ByVal useDataSource As Boolean) As System.Collections.ICollection

 

        Dim l_aFields As New ArrayList()

        For Each l_oField As DataControlField In MyBase.CreateFieldSet(dataItem, useDataSource)

            l_aFields.Add(l_oField)

        Next

 

        ' we have a predefined set of database columns to display

        For Each l_sColumn As String In Me.DisplayColumns

 

            ' see if the column exists in the database

            If _oDP.IsColumn(Me.PrimaryTable, l_sColumn) Then

 

                ' determine the language specific string to use for HeaderText

                Dim l_sHeader As String = wsLanguage.GetExternalDataForLanguage(Me.PrimaryTable, l_sColumn, "columnname")

                If wsUtils.IsEmpty(l_sHeader) And l_sColumn.ToUpper = "ID" Then

                    l_sHeader = l_sColumn

                End If

 

                ' 

                Dim l_oColumn As New TemplateField()

                l_oColumn.HeaderText = l_sHeader & " : "

                l_oColumn.ItemTemplate = New wsDetailsViewTemplate("literal", l_sColumn)

                If l_sColumn.ToUpper = "ID" Then

                    ' primary key always just a Literal (and thus never editable)

                    l_oColumn.EditItemTemplate = New wsDetailsViewTemplate("literal", l_sColumn)

                    l_oColumn.InsertItemTemplate = New wsDetailsViewTemplate("literal", l_sColumn)

                Else

                    l_oColumn.EditItemTemplate = New wsDetailsViewTemplate("textbox", l_sColumn)

                    l_oColumn.InsertItemTemplate = New wsDetailsViewTemplate("textbox", l_sColumn)

                End If

 

                ' add the new TemplateField to the Fields collection

                l_aFields.Add(l_oColumn)

 

            End If

 

        Next

 

        Return l_aFields

 

    End Function

 

    Protected Overrides Sub OnItemUpdating(ByVal e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs)

 

        Dim l_aColumns As New Hashtable, l_iIndex As Integer = 0

 

        If Me.Fields.Count > 0 Then

 

            For l_iI As Integer = 0 To Me.Rows.Count - 1

                Dim l_oNormal As DataControlFieldCell = Me.Rows(l_iI).Cells(0)

                Me.Fields(l_iI).ExtractValuesFromCell(e.Keys, l_oNormal, DataControlRowState.Normal, True)

                Dim l_oEdit As DataControlFieldCell = Me.Rows(l_iI).Cells(1)

                Me.Fields(l_iI).ExtractValuesFromCell(e.NewValues, l_oEdit, DataControlRowState.Edit, False)

            Next

 

            ' the following is for testing only... these always turn up empty

            For Each l_sKey As String In e.Keys

                Dim l_sKeyValue = e.Keys(l_sKey)

            Next

            For Each l_sKey As String In e.NewValues

                Dim l_sNewValue = e.NewValues(l_sKey)

            Next

 

        End If

 

        'Be sure to call the base class's OnItemUpdating method!

        MyBase.OnItemUpdating(e)

 

    End Sub

 

#End Region

 

#Region "Custom properties (using ViewState)"

...

#End Region

 

End Class

 

==================================================================

 

Public Class wsDetailsViewTemplate

    Implements ITemplate

 

    Dim _sControlType As String

    Dim _sColumnName As String

 

    Sub New(ByVal p_sControlType As String, ByVal p_sColumn As String)

        _sControlType = p_sControlType

        _sColumnName = p_sColumn

    End Sub

 

    Sub InstantiateIn(ByVal p_oContainer As Control) _

        Implements ITemplate.InstantiateIn

 

        Select Case _sControlType.ToLower

            Case "textbox"

                Dim l_oTextBox As New TextBox

                l_oTextBox.ID = _sColumnName

                AddHandler l_oTextBox.DataBinding, AddressOf OnDataBinding

                p_oContainer.Controls.Add(l_oTextBox)

            Case Else

                ' implement Literal as default

                Dim l_oLiteral As New Literal

                l_oLiteral.ID = _sColumnName

                AddHandler l_oLiteral.DataBinding, AddressOf OnDataBinding

                p_oContainer.Controls.Add(l_oLiteral)

        End Select

 

    End Sub

 

    Protected Sub OnDataBinding(ByVal sender As Object, ByVal e As System.EventArgs)

 

        Dim l_oControl As Object, l_oContainer As wsExtendedDetailsView

        Select Case _sControlType.ToLower

            Case "textbox"

                l_oControl = TryCast(sender, TextBox)

                l_oContainer = TryCast(l_oControl.NamingContainer, wsExtendedDetailsView)

                l_oControl.Text = DataBinder.Eval(l_oContainer.DataItem, _sColumnName)

            Case Else

                ' implement Literal as default

                l_oControl = TryCast(sender, Literal)

                l_oContainer = TryCast(l_oControl.NamingContainer, wsExtendedDetailsView)

                l_oControl.Text = DataBinder.Eval(l_oContainer.DataItem, _sColumnName)

        End Select

 

    End Sub

 

End Class

Open in new window

0
Comment
Question by:MarjaR
1 Comment
 
LVL 1

Accepted Solution

by:
MarjaR earned 0 total points
ID: 24392903
Found a solution that works for me:

I've now implemented a custom GetValues function which gets called in OnItemUpdating (see below)


    Protected Function GetValues() As Hashtable

        Dim l_aValues As New Hashtable

        For Each l_oRow As DetailsViewRow In Me.Rows

            ' only look at DataRow

            If l_oRow.RowType = DataControlRowType.DataRow Then

                Dim l_oCell As DataControlFieldCell = CType(l_oRow.Cells(0), DataControlFieldCell)

                If l_oCell.ContainingField.ShowHeader Then

                    ' if we are showing the header for this row then the data is in the adjacent cell

                    l_oCell = CType(l_oRow.Cells(1), DataControlFieldCell)

                End If

                If l_oCell.Controls.Count > 0 Then

                    ' we do have some controls in this cell

                    ' capture their values

                    For Each l_oControl As Control In l_oCell.Controls

                        Dim l_sID As String = l_oControl.ID

                        If l_sID.ToUpper <> "ID" Then

                            Dim l_sValue As String = ""

                            ' 1st see if it is a Literal

                            If TypeOf l_oControl Is Literal Then

                                Dim l_oLiteral As Literal = CType(l_oControl, Literal)

                                l_sValue = l_oLiteral.Text

                            ElseIf TypeOf l_oControl Is TextBox Then

                                Dim l_oTextBox As TextBox = CType(l_oControl, TextBox)

                                l_sValue = l_oTextBox.Text

                            End If

                            l_aValues.Add(l_sID, l_sValue)

                        End If

                    Next

                End If

            End If

        Next

        Return l_aValues

    End Function
 

    Protected Overrides Sub OnItemUpdating(ByVal e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs)
 

        _aControlValues = GetValues()
 

        If _aControlValues.Count > 0 Then

            ' updated record with new values

            Dim l_iID As Long = Me.PrimaryKeyValue

            l_iID = _oDP.EditRecord(l_iID, Me.PrimaryTable, _aControlValues)

        End If
 

        'Be sure to call the base class's OnItemUpdating method

        MyBase.OnItemUpdating(e)
 

    End Sub

Open in new window

0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Any Third party toll for Integrating chat system on ASP.NET ? 2 34
C# Offline Apllication 5 48
Host asp.net pages 5 25
What .NET URL re-routing tool did I use? 2 31
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.
Concerto provides fully managed cloud services and the expertise to provide an easy and reliable route to the cloud. Our best-in-class solutions help you address the toughest IT challenges, find new efficiencies and deliver the best application expe…

929 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now