MarjaR
asked on
Problems with OnItemUpdating for DetailsView
My issue is similar to https://www.experts-exchange.com/questions/23004459/Trouble-with-DetailsView-OnItemUpdating.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 .
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.