News

Coders 4 Charities is live!!!
Add to Technorati Favorites

My Stats

  • Posts - 46
  • Comments - 118
  • Trackbacks - 33

Twitter












Tag Cloud


Recent Comments


Recent Posts


Archives


Post Categories


Image Galleries


Blogs I read


Company Links


Fun Stuff


Kansas City User Groups


My CMS Projects


June 2005 Entries

Maintaining checkbox "checked" state in ASP.NET DataGrid


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

posted @ Thursday, June 30, 2005 2:25 PM | Feedback (13) |


Awesome file share server


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

posted @ Friday, June 10, 2005 7:08 PM | Feedback (0) |