The subject of this blog should say it all. I've searched everywhere for a solution to this, to no avail. Essentially, what I wanted to do is this:
I needed to present a paged, filtered DataGrid to a user, with checkboxes added programmatically, and maintain the state of the checkboxes as PostBacks occurred.
There were tons of articles on how to programmatically add a checkbox to a DataGrid, which I had already figured out how to do. One way to do this (very inefficiently) is:
Stash the DataSet, DataView and DataGrid on the Session so it can be pulled after PostBacks. Then, iterate thru the DataGrid, then nest thru the DataSet, and set a Boolean value on the DataSet to match the value of the checkbox. So, you're looping thru the grid grid.Items.Count times, and for every item in the grid, you're looping thru the DataSet ds.Tables(”Table”).Rows.Count times. And that's just to capture the checkboxes.
As the user returns to that page of the grid, you'll need to pull the DataView off the Session, evaluate a column in the DataView against a column in the e.Items collection (from the DataGridItemEventArgs in the ItemCreated() event handler), and “check“ the box accordingly. Again, this is nested looping at it's worst.
This worked, but as I paged through, or as I changed the RowFilter on the dataview, the performance was horrible. I'm not know for writing efficient code, but this was ridiculous.
Make 'em sick, make 'em well.
So, after I filled my DataSet, I loaded my unique compare column (from the DataSet) along with a True/False value into a Collection. Since the Collection.Items() collection is read-only, I had to create a basic Class that exposed a property “CheckState“ to return True or False. That way, when I wanted to modify the value of the item in the collection for the given key, I could just modify a reference to the CheckState object. There will be code snippets below, btw.
So by now on PageLoad, I've got a filled DataSet, and a Collection representing key information. I stash that onto the Session, and I wait for a PostBack. When I get the PostBack, I loop thru the DataGrid, check the state of the checkboxes, and updating the collection accordingly. Again, stashing it back to the Session when I'm done.
When the page or RowFilter changes, I need to re-check checkboxes as necessary. I plugged into the ItemCreated event handler, and used the e.Items collection to fetch my key value, and I compared it to the Item in the Collection. If True, check the box.
Below is the code that I used to do all this (variable and table names have been changed to protect their anonymity).
Reply to this blog or email me if you wanna talk about it.
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim lcv As Integer
Dim cb As CheckBox
Dim ds As DataSet
Dim oState As CheckState
If IsPostBack Then
' pull the collection off the Session
m_Collection = Session("Collection")
For lcv = 0 To dg.Items.Count - 1
' get a checkbox object from the datagrid to evaluate
cb = dg.Items(lcv).Cells(0).Controls(0)
' get the StateCheck object reference from the collection
' that matches the key column from the datagrid
oState = m_Collection.Item(dg.Items(lcv).Cells(1).Text)
' update the referenced object (which should update the collection)
If cb.Checked Then
oState.State = True
Else
oState.State = False
End If
' now that we've updated, push the collection back to Session
Session("Collection") = m_Collection
Next
Exit Sub
End If
PopulateGrid()
End Sub
Private Sub PopulateGrid()
Dim oDR As SqlDataReader
Dim parmPostNum As SqlParameter
Dim parm As SqlParameter
Dim tableNames(0) As String
Dim iCompanyID As Int32
Dim dvPostMembers As DataView
Dim lcv As Integer
Dim lcv2 As Integer
Dim cb As CheckBox
Dim iCardNumber As Integer
Dim oState As Integer
...
' Fill the DataSet here
...
m_Collection = New Collection
' set all to False, and add to the collection
For lcv = 0 To ds.Tables("Table").Rows.Count - 1
ds.Tables("Table").Rows(lcv).Item("CheckBoxChecked") = False
oState = New CheckState
oState.State = False
m_Collection.Add(oState, ds.Tables("Table").Rows(lcv).Item("KeyValue"))
Next
Session("Collection") = m_Collection
dv = New DataView(ds.Tables("Table"))
dv.RowFilter = "Column='filter'"
Session("DataView") = dv
Session("DataSet") = ds
dg.DataSource = dv
dg.DataBind()
End Sub
Private Sub dg_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemCreated
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
AddCheckbox(e)
End If
End Sub
Private Sub AddCheckbox(ByVal e As DataGridItemEventArgs)
Dim cb As New CheckBox
Dim dv As DataView
Dim keyval As String
Dim oState As CheckState
dv = Session("DataView")
keyval = dv.Item(e.Item.ItemIndex).Row.Item(13)
' pull the collection off the Session
m_Collection = Session("Collection")
' get the CheckState of the current item in the data view
oState = m_Collection.Item(keyval)
cb.Checked = oState.State
cb.EnableViewState = True
cb.ID = "chkItemChecked"
cb.AutoPostBack = False
cell.HorizontalAlign = HorizontalAlign.Right
cell.Controls.Add(cb)
End Sub
Public
Class CheckState
Private m_bCheckState As Boolean
Public Property State() As Boolean
Get
Return m_bCheckState
End Get
Set(ByVal Value As Boolean)
m_bCheckState = Value
End Set
End Property
End Class
Not sure if there's already a post about this (I'm sure there is), but I just stumbled on a really cool file share server out “there”. It's called RapidShare, and you can click here to go to it.
Essentially, you Browse your machine for a file to upload, upload it, and when it's done, it displays two links: for downloading and deleting. The cool thing is that there is *NO* browsing/searching capability to this site, so you can put family pics/vids up without worrying about it making onto eBaum's World or anything.
The download functionality is kinda hokey, because they make you wait 60 seconds to receive a download “ticket” (presumably to prevent multiple, frequent downloads). But it's still cool cuz you can upload up to 50MB at a time (fragmented files are kool and the gang too), and did I mention it's free? Files not used after 30 days get auto-nuked.
Doug