Question

I have a databound grid with a templated field column that is a checkbox. When the user checks the checkbox, it will autopostback and update the row to indicate the box's check state.

My first attempt was to simply use the OnCheckedChanged method, but when this gets called, I have no way to know which row the checkbox came from. Thus, I don't know which row to update.

Can anyone suggest a method to determine which row the checkbox that fired the oncheckedchanged event came from? Or can you suggest a better way to achieve what I need to do?

I cannot bind the checkbox to the data column because I do not want the checkbox disabled in select mode, and do not wish to require the user to enter edit mode to change the value. I also need all rows to be editable. So, the best route seems to be in a templated column.

Was it helpful?

Solution

You could find the checked Checkbox by iterating over the rows.

Protected Sub MyCheckBoxCheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
    For Each row As GridViewRow In GridView1.Rows
        Dim cb As CheckBox = DirectCast(row.FindControl("MyCheckBoxID"), CheckBox)
        If sender Is cb AndAlso cb.Checked Then
            'Do something ...'
            Exit For
        End If
    Next
End Sub

This isn't as inefficient as it looks like(when the Grid's PageSize is not too high).

You can also get the GridViewRow via Checkbox.Parent.Parent:

  Protected Sub MyCheckBoxCheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
        Dim cb As CheckBox = DirectCast(sender, CheckBox)
        Dim row As GridViewRow = DirectCast(cb.Parent.Parent, GridViewRow)
        row.BackColor = DirectCast(IIf(cb.Checked, Color.Red, Color.White), Color)
  End Sub

This is faster as option 1 but if you f.e. would nest the Checkbox in a Table in the future, this wouldn't work anymore without adjustment.

I would normally prefer option 1, because in an event-handler one millisecond more or less doesn't matter.


Update: getting the GridViewRow via NamingContainer is another(in my opinion the best) option:

Dim row As GridViewRow = DirectCast(cb.NamingContainer, GridViewRow)

This even still works when you nest the Checkbox inside other Controls like a Table.

OTHER TIPS

I don't think there's a way to do this as stated without handling the RowEditing, RowUpdating, and RowCancelingEdit events.

Alternatively, I'd suggest adding a CommandField to the GridView, like so:

<asp:CommandField ShowSelectButton="true" />

You'll need to handle the GridView.SelectedIndexChanging, again like so:

    void GridView_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
    {
        GridView.SelectedIndex = e.NewSelectedIndex;
    }

Once you're in SelectedIndexChanging, you can use GridView.Rows[e.NewSelectedIndex].FindControl("id") to get the control you need -- assuming this funcitonality is still critical to you.

Edit: I just read your update, and I'm not entirely sure what you're trying to achieve here. It sounds like you're familiar with the CommandField. What do you want your website to do when you check this checkbox that has to be done independently the row states?

Edit 2: You could also cast object sender to your CheckBox, and find the appropriate GridRow using .Parent(), but this has always felt extremely hacky to me.

Edit 3: I swear, I'm going to stop editing this eventually.

I've never tried this, but you could get a reference to CheckBox.ClientID and try going through each row in the GridView, and calling GridViewRow.FindControl(CheckBox.ClientID). I really have no idea if this will work, though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top