views:

24

answers:

2

Hi

I am dynamically binding a typed list to a GridView control. The Grid View Control is in an asp.net page that is wrapped in an asp:UpdatePanel (Ajax). The first column contains a checkbox control. Only one checkbox may be checked in this column. If the user checks a checkbox, all other checkbox must be unchecked.

I am trying to achieve this using client-side script without success. In the handler for the GridView’s RowDatabound event, have attempted to add an attribute to the CheckBox contained within the cell.

protected void ErrorGridView_RowDatabound(object sender, GridViewRowEventArgs e)
  {

     if (e.Row.RowType == DataControlRowType.DataRow)
     {

        if(e.Row.Cells[0].HasControls())
        {
           foreach (var control in e.Row.Cells[0].Controls)
           {
              if (!(control is CheckBox)) continue;

              var checkBox = (CheckBox)control;
              checkBox.Attributes.Add("CheckedChanged", "errorCheckChanged");
              return;
           }
        }           
     }

The client side script is registered on the Page_Load event handler - as below:

if (!Page.ClientScript.IsClientScriptBlockRegistered("ErrorsCheckBoxHandler")) Page.ClientScript.RegisterClientScriptBlock(GetType(),"ErrorsCheckBoxHandler", "function errorCheckChanged() {window.alert(\"here\"); }");

The problem is that the function is not called when any checkboxes are clicked. Hopefully someone can shed some light as to what am I missing here?

Also, what would be the best way to perform the de-selection of the any other checkboxes that are checked in the target column?

My plan would be to change the 'errorCheckChanged' function to take one parameter (the checkbox object). I would change the above code; adding to the attribute addition signature:

checkBox.Attributes.Add("CheckedChanged", "errorCheckChanged(this)");

Hopefully, I will then be able to:
(1) determine if the checkbox state is 'checked'. (If it is 'checked', then continue below steps)
(2) find the checkbox parent (= cell) and then determine the affected GridView Row.
(3) Loop through all rows setting the checkboxes to 'Checked=false' except of the current row.

Would this be considered the right approach?

Thanks

Grant

A: 

use the onclick attribute rather than CheckChanged. i don't think that's a valid js event. so

checkBox.Attributes.Add("onclick", "errorCheckChanged(this);");

to get a list of checkboxes you can do

js:

var grid = document.getElementById('<% =GridView1.ClientID %>');
var checks = grid.getElementsByTagName('input');

you'll have to check the type attribute to make sure it's a checkbox, or you can give all the checkboxes a specific class to logically group them. anyway you can check your clicked element id against the list.

lincolnk
Thanks for your quick reply. My first attempt had been using the 'onclick' event. Only the detail entered when registering the script block can be viewed via View -> Source in the browser. Even when I was able to fire the event (when register the onclick event with the actual column (not the checkbox in the colum), the source does not reveal the attribute for each row. I think this is because the UpdatePanel encrypts the information.
Grant Sutcliffe
generally what you see when viewing source is what was loaded originally. any javascript changes won't be applied after that. if you're using IE8, you can bring up the developer tools window (f12) which will give you an html view, and after the ajax request completes you can refresh the html contents (f5).
lincolnk
I removed the panels in order to view the Htlm. I had not thought of refreshing the html view in the developer tool window. Thanks for the tip. Will do this in future
Grant Sutcliffe
A: 

You can also add the onclick event of checkbox in design time.

<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkSelect" onclick="errorCheckChanged(this)" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>

And the JavaScript looks like

function errorCheckChanged(chkBox){  
    var gridView = document.getElementById('<% =GridView1.ClientID %>');   
    var Elements = gridView.getElementsByTagName('input');   

    for(var i = 0; i < Elements.length; i++){
        if(Elements[i].type == 'checkbox' && Elements[i].id != chkBox.id && chkBox.checked)
            Elements[i].checked = false;
    }
}
Selva TS
Great stuff Selva. Following this concept worked. Except, I was not able to get the - getElementById('<% =myGridView.ClientID %>' to work. I had to hard code the value. Thanks for your help.
Grant Sutcliffe