Hi Scott,
On the bright side - I've learned A LOT over the last three days.
Teemu's article was key (
http://aspalliance.com/135). I was expecting
to see values stored for the controls on a page, but that's not the
way it works.
Yes, I can iterate through the datagriditems to get the value of the
datagrid but ONLY because I have saved the datasest in a custom
viewstate and I'm repopulating the datagrid with the saved dataset
from the viewstate.
I've tested this with this code in the code behind page:
Public Class WebForm2
Inherits System.Web.UI.Page
Protected WithEvents LinkButton1 As
System.Web.UI.WebControls.LinkButton
Protected WithEvents panel1 As System.Web.UI.WebControls.Panel
Dim mt As New myTracker()
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
If Not Page.IsPostBack Then
mt.myDatabind()
End If
panel1.Controls.Add(mt.getPanel)
End Sub
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
If Not (savedState Is Nothing) Then
Dim myState As Object() = CType(savedState, Object())
'panelJobDetail = New JobDetails(10)
If Not (myState(0) Is Nothing) Then
MyBase.LoadViewState(myState(0))
End If
If Not (myState(1) Is Nothing) Then
mt.LoadViewState(myState(1))
End If
End If
End Sub
Protected Overrides Function SaveViewState() As Object
Dim myState(1) As Object
myState(0) = MyBase.SaveViewState()
myState(1) = mt.SaveViewState
Return myState
End Function
Protected Overrides Sub TrackViewState()
mt.TrackViewState()
MyBase.TrackViewState()
End Sub
End Class
Here's my code for the mt object:
Imports System.Web.UI
Public Class myTracker
Implements IStateManager
Dim ds As New DataSet()
Dim mg As New myGrid()
Private _isTrackingViewState As Boolean
Private _viewState As StateBag
Private _savedDetail As Object
Public Sub New()
End Sub
Public Function getPanel() As Panel
Return mg.getPanel()
End Function
Protected ReadOnly Property ViewState() As StateBag
Get
If _viewState Is Nothing Then
_viewState = New StateBag(False)
If _isTrackingViewState Then
CType(_viewState, IStateManager).TrackViewState()
End If
End If
Return _viewState
End Get
End Property
Public ReadOnly Property IsTrackingViewState() As Boolean
Implements IStateManager.IsTrackingViewState
Get
Return _isTrackingViewState
End Get
End Property
Public Sub LoadViewState(ByVal savedState As Object) Implements
IStateManager.LoadViewState
If Not (savedState Is Nothing) Then
CType(ViewState, IStateManager).LoadViewState(savedState)
End If
_savedDetail = ViewState("detail")
If Not (savedState Is Nothing) Then
mg.Detail = ViewState("detail")
End If
End Sub
Public Function SaveViewState() As Object Implements
IStateManager.SaveViewState
Dim currentDetail, savedDetail As Object
currentDetail = mg.Detail
savedDetail = ViewState("detail")
If Not mg.compare(currentDetail, savedDetail) Then
ViewState("detail") = currentDetail
End If
If Not IsNothing(_viewState) Then
Return CType(_viewState, IStateManager).SaveViewState
End If
End Function
Public Sub TrackViewState() Implements
IStateManager.TrackViewState
'If Not IsNothing(_viewState) Then
ViewState("detail") = mg.Detail
' End If
_isTrackingViewState = True
If Not IsNothing(_viewState) Then
CType(_viewState, IStateManager).TrackViewState()
End If
End Sub
Public Sub myDatabind()
mg.DataBind()
End Sub
End Class
Public Class myGrid
Inherits Panel
Implements IComparer
Dim ds As New DataSet()
Dim dg As New DataGrid()
Public Sub New()
Controls.Clear()
dg.Columns.Clear()
dg.AutoGenerateColumns = False
Dim col1 As New TemplateColumn()
col1.ItemTemplate = New myEditItemTemplate("ServiceID", 5)
col1.HeaderText = "ServiceID"
dg.Columns.Add(col1)
Dim col2 As New TemplateColumn()
col2.ItemTemplate = New myEditItemTemplate("Description", 20)
col2.HeaderText = "Description"
dg.Columns.Add(col2)
Dim col3 As New TemplateColumn()
col3.ItemTemplate = New myEditItemTemplate("Qty", 5)
col3.HeaderText = "Qty"
dg.Columns.Add(col3)
Controls.Add(dg)
ds.Tables.Add("one")
ds.Tables(0).Columns.Add("ServiceID")
ds.Tables(0).Columns.Add("Description")
ds.Tables(0).Columns.Add("Qty")
Dim dr As DataRow
dr = ds.Tables(0).NewRow
dr.Item(0) = "scott"
dr.Item(1) = "kent"
dr.Item(2) = "nichols"
ds.Tables(0).Rows.Add(dr)
ds.AcceptChanges()
dg.DataSource = ds.Tables(0)
End Sub
Public Property Detail() As Object
Get
Return ds
End Get
Set(ByVal Value As Object)
ds = Value
dg.DataSource = Value
dg.DataBind()
End Set
End Property
Public Sub myDatabind()
dg.DataBind()
End Sub
Public Function getPanel() As Panel
Return Me
End Function
Public Function compare(ByVal x As Object, ByVal y As Object) As
Integer Implements IComparer.Compare
Dim ds1 As New DataSet()
Dim ds2 As New DataSet()
ds1 = CType(x, DataSet)
ds2 = CType(y, DataSet)
If ds1.GetXml = ds2.GetXml Then
Return 0
Else
Return 1
End If
End Function
End Class
Class myEditItemTemplate
Implements ITemplate
Private _colname As String = ""
Private _width As Integer
Public Sub New(ByVal ColName As String, ByVal width As Integer)
_colname = ColName
_width = width
End Sub
Sub instantiatein(ByVal container As Control) Implements
ITemplate.InstantiateIn
Dim tb As New TextBox()
tb.Columns = _width
'This is so it would be added to the automatic populating
routine
tb.ID = "txt" & _colname
AddHandler tb.DataBinding, AddressOf bindTextBox
container.Controls.Add(tb)
End Sub
Public Sub bindTextBox(ByVal sender As Object, ByVal e As
EventArgs)
Dim tb As TextBox = CType(sender, TextBox)
Dim container As DataGridItem = CType(tb.NamingContainer,
DataGridItem)
tb.Text = Convert.ToString(DataBinder.Eval((CType(container,
DataGridItem)).DataItem, _colname))
End Sub
End Class
The cool news is THIS WORKS. If you have an aspx page that has a
linkbutton on it and you click it (just so the page will do a
postback) the datagrid stays intact and the textxbox on the
dynamically created datagrid retains any value entered into it.
The bad news is when I move this test code over to my production
program I run into a small problem - The datagrid does not retain new
values on the FIRST POSTBACK. On subsequent postbacks it works, but
not the first time.
It seems like I have the answer in front of me... but I just can't
find it.
Cheers,
Scott