Solved

Dynamic GridView w/ checkboxes not executing CheckedChanged Event

Posted on 2008-10-03
9
7,389 Views
Last Modified: 2013-12-17
I have a somewhat complicated GridView that contains 3 static columns and a dynamic number of columns of checkboxes.  I have the majority of this gridview working except that I can not get the CheckedChanged event to fire when I click a checkbox.  It was working until I added code in my on_DataBinding event to check those checkboxes that should be checked.  The checked value is not a single field in the database so I couldn't databind it directly.  The way I am doing it works even though it is ugly and inefficient.  Everything loads fine and the correct boxes in the GridView are checked properly.  I just can not get it to fire the CheckedChanged event anymore.
ASPX

<asp:GridView ID="gvTest" runat="server" AutoGenerateColumns="False" OnRowDataBound="gvTest_OnRowDataBound" >

   <Columns>

      <asp:BoundField HeaderText="Doc ID" DataField="Doc_ID" />

      <asp:TemplateField HeaderText="Author/Title">

         <ItemTemplate>

           <asp:Label ID="lblAuthor" runat="server" Text='<%#Eval("Author")%>'></asp:Label>                    

             <asp:HyperLink ID="lblTitle" runat="server" Text='<%#Eval("Title")%>' NavigateUrl='<%#GetURL(Eval("Doc_ID").ToString(), Eval("Filename").ToString())%>'></asp:HyperLink>  

          </ItemTemplate>

        </asp:TemplateField>

     </Columns>

</asp:GridView>

 

ASPX.CS

public partial class Gridview : System.Web.UI.Page

{

  protected void Page_Load(object sender, EventArgs e)

  {

     int intNumClasses = 0;

     string strSQL = "SELECT DISTINCT * FROM LK_PRSN_CLASS l,curriculum c where prsn_id=xxxxxxx and l.curriculum_id=c.curriculum_id";

     SqlConnection conPRSN = new SqlConnection ConfigurationManager.AppSettings["conPRSN"]);

     SqlCommand cmdClasses = new SqlCommand(strSQL, conPRSN);

     conPRSN.Open();

     SqlDataReader drClasses;

     drClasses = cmdClasses.ExecuteReader();

            

     ArrayList arrInner = new ArrayList();

     ArrayList arrClass = new ArrayList();

 

     while (drClasses.Read())

     {

        arrInner.Add(drClasses["Curriculum_id"] + "_" + drClasses["Course_ID"] + "_" + drClasses["SectionNO"]);

        arrInner.Add(drClasses["ABBR"] + " " + drClasses["Course_ID"] + "<br>Sec. " + drClasses["SectionNo"].ToString());

        arrClass.Add(arrInner);

        intNumClasses += 1; //counting the number of classes for later use

      }

      conPRSN.Close();

      drClasses = null;

            

      //initalize the test gridview

     strSQL = "SELECT Doc_ID, FileName, Title, Author, PRSN_ID FROM VW_INSTR_DOC_LIST WHERE (PRSN_ID = xxxxxxxx) order by author, title";

     SqlConnection conEreserve = new SqlConnection(ConfigurationManager.AppSettings["conEReserve"]);

     SqlDataAdapter daGV = new SqlDataAdapter(strSQL, conEreserve);

     DataSet dsGV = new DataSet();

     conEreserve.Open();

     daGV.Fill(dsGV, "Documents");

     ArrayList arrDocs = new ArrayList();

     foreach (DataRow row in dsGV.Tables[0].Rows)

     {

        ListItem listitem = new ListItem();

        listitem.Text = row["doc_id"].ToString();

        arrDocs.Add(listitem);

      }

      conEreserve.Close();

 

       //add checkbox templates to gridview

       for (int i = 1; i < intNumClasses * 2; i++)

       {

          TemplateField tfCheck = new TemplateField();

          tfCheck.HeaderTemplate = new GridViewCheckBoxTemplate(DataControlRowType.Header,

          ((ArrayList)arrClass[0])[i].ToString());

          tfCheck.ItemTemplate = new GridViewCheckBoxTemplate(DataControlRowType.DataRow,((ArrayList)arrClass[0])[i].ToString());

          gvTest.Columns.Add(tfCheck);

                

          i++; //going by twos

        }

            

       gvTest.DataSource = dsGV;

       gvTest.DataBind();

     }

     public class GridViewCheckBoxTemplate : ITemplate

     {

        private DataControlRowType templateType;

        private string columnName;

 

        public GridViewCheckBoxTemplate(DataControlRowType type, string colname)

        {

           templateType = type;

           columnName = colname;

        }

 

        public void InstantiateIn(System.Web.UI.Control container)

        {

          switch (templateType)

          {

             case DataControlRowType.Header:

                  Label header = new Label();

                  header.Text = columnName;

                  container.Controls.Add(header);

                  break;

              case DataControlRowType.DataRow:

                  CheckBox cb = new CheckBox();

                  cb.CheckedChanged += new EventHandler(this.cb_CheckedChanged);

                  cb.AutoPostBack = true;

                  cb.DataBinding += new EventHandler(this.ctl_OnDataBinding);

                  container.Controls.Add(cb);

                  break;

              default: break;

           }//end switch

       }//end instantiateIn

       public void ctl_OnDataBinding(object sender, EventArgs e)

       {

          //turn on the classes

           CheckBox cb = (CheckBox)sender;

           cb.ID = "tempID";

           GridViewRow selectedrow = (GridViewRow)cb.NamingContainer;

           System.Web.UI.WebControls.GridView dd = (System.Web.UI.WebControls.GridView)selectedrow.NamingContainer;

           int intCellIndex = 0; //the location of the cell in the row

           for (int intCount = 2; intCount < selectedrow.Cells.Count; intCount++)

           {

             if (((CheckBox)selectedrow.Cells[intCount].Controls[0]).ID == "tempID")

             {

                intCellIndex = intCount;

                intCount = selectedrow.Cells.Count;

             }

                }

                string header = ((Label)dd.HeaderRow.Cells[intCellIndex].Controls[0]).Text;

 

                string strSQL = "SELECT Count(*) FROM TURNED_ON_CLASSES WHERE PRSN_ID=10005536 AND CURRIC_ABBR='" + header.Substring(0, 4) + "' " +

                        " AND COURSE='" + header.Substring(5, 3) + "' AND SECTION='" + header.Substring(header.LastIndexOf(" ")+1, header.Length - header.LastIndexOf(" ")-1) + "' AND " +

                        "DOC_ID=" + selectedrow.Cells[0].Text;

 

               // HttpContext.Current.Trace.Warn("ctl SQL: " + strSQL);

                SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["conEreserve"]);

                SqlCommand cmd = new SqlCommand(strSQL, con);

                con.Open();

                int Turned_On = Convert.ToInt32(cmd.ExecuteScalar());

                con.Close();

                if (Turned_On != 0) cb.Checked = true;

                cb.ID = "";

            }           

 

            // helper method to convert CamelCaseString to Camel Case String

            // by inserting spaces

            private string BreakCamelCase(string CamelString)

            {

                string output = string.Empty;

                bool SpaceAdded = true;

 

                for (int i = 0; i < CamelString.Length; i++)

                {

                    if (CamelString.Substring(i, 1) ==

                        CamelString.Substring(i, 1).ToLower())

                    {

                        output += CamelString.Substring(i, 1);

                        SpaceAdded = false;

                    }

                    else

                    {

                        if (!SpaceAdded)

                        {

                            output += " ";

                            output += CamelString.Substring(i, 1);

                            SpaceAdded = true;

                        }

                        else

                            output += CamelString.Substring(i, 1);

                    }

                }

 

                return output;

            }

           

            public void cb_CheckedChanged(object sender, EventArgs e)

            {

                CheckBox cb = (CheckBox)sender;

                cb.ID = "tempID";//cell has to have a temporary ID so that it can be found in the row later.

                HttpContext.Current.Trace.Warn("got to cb checked" + cb.ID);

                

                GridViewRow selectedrow = (GridViewRow)cb.NamingContainer;

 

                System.Web.UI.WebControls.GridView dd = (System.Web.UI.WebControls.GridView)selectedrow.NamingContainer;

 

                HttpContext.Current.Trace.Warn("ID: " + selectedrow.Cells[0].Text);

                int intCellIndex = 0; //the location of the cell in the row

                for (int intCount = 2; intCount < selectedrow.Cells.Count; intCount++)

                {

                    if (((CheckBox)selectedrow.Cells[intCount].Controls[0]).ID == "tempID")

                    {

                        intCellIndex = intCount;

                        intCount = selectedrow.Cells.Count;

                    }

                }

                //int cellnumber = ((GridViewRow)cb.NamingContainer).

                HttpContext.Current.Trace.Warn("c: " + intCellIndex);

                string header = ((Label)dd.HeaderRow.Cells[intCellIndex].Controls[0]).Text;

                HttpContext.Current.Trace.Warn("Header: " + header);

 

                //save the class to the database as turned on OR delete if turning it off

                string strSQL = "";

                if (cb.Checked)

                {

                    strSQL = "INSERT INTO TURNED_ON_CLASSES (PRSN_ID, CURRIC_ABBR, COURSE, SECTION, DOC_ID " +

                            "VALUES (xxxxxxxx, '" + header.Substring(0, 4) + "', '" + header.Substring(5, 3) + "', " +

                            "'" + header.Substring(header.LastIndexOf(" "), header.Length - header.LastIndexOf(" ")) + "', " +

                            selectedrow.Cells[0].Text + ")";

                    HttpContext.Current.Trace.Warn("INSERT: " + strSQL);

                }

                else //delete from db

                {

                    strSQL = "DELETE FROM TURNED_ON_CLASSES WHERE PRSN_ID=xxxxxxxxAND CURRIC_ABBR='" + header.Substring(0, 4) + "', " +

                        "' AND COURSE='" + header.Substring(5, 3) + "' AND SECTION='" + header.Substring(header.LastIndexOf(" "), header.Length - header.LastIndexOf(" ")) + "' AND " +

                        "DOC_ID=" + selectedrow.Cells[0].Text + ")";

                    HttpContext.Current.Trace.Warn("DELETE: " + strSQL);

                }

               

                

            }

        }//end public class GridViewCheckBoxTemplate : ITemplate

 

        public void cb_CheckedChanged(object sender, EventArgs e)

        {

           //this function is required or the checkboxes can't seem to find the class version cb_CheckChanged

            HttpContext.Current.Trace.Warn("got to cb checked outside class");

        }

 

        public string GetURL(string doc_id, string filename)

        {  //returns a URL...Code available upon request

        }

    }

Open in new window

0
Comment
Question by:rclint
  • 5
  • 2
  • 2
9 Comments
 
LVL 15

Expert Comment

by:NazoUK
ID: 22636489
A couple of thoughts:
1. You seem to be databinding the gridview every page_load, this will probably mess up control events. Wrap it in a (!IsPostBack) block (unless you have viewstate turned off for the gridview)

2. Why are you giving all the checkboxes temporarys IDs  then ""? I'm not sure if this is affecting it or not but it doesn't seem like good practice.
0
 
LVL 1

Author Comment

by:rclint
ID: 22636578
Thanks for responding.  

There are probably a lot of unsound practices in this application. :)  I have been going back and forth trying different things for the past couple weeks.  I even started from scratch at a couple points.

1.  I am data_binding every page_load because up till this point it hasn't seemed to affect it either way.  I will look into that aspect though and see if that could be the problem.  As I stated before though, the checkchanged event fired correctly before I put code into the ctl_OnDataBinding event.
2. I assign a tempID so that I can find the column number of the checkbox that is clicked.  It has no ID otherwise for me to determine that.  I then iterate through teh row columns until I find the column with that checkbox.  If you know of an easier way then I would very much like to hear it.  It was the only way I could find the column number of a particular cell.  If I don't set the ID back to "" then it gives me the multiple controls with the same name error.
0
 
LVL 15

Expert Comment

by:NazoUK
ID: 22636689
How are you generating the gridview? With autogenerate columns = true? Or are you adding the the checkboxes through some other method?

I would expect the checkboxes to have unique IDs if they are automatically generated. What happens if you assign the value of cb.ID to a variable then use that to try to find the index in the row?
0
 
LVL 1

Author Comment

by:rclint
ID: 22636771
Autogenerate columns is False.  I am adding checkboxes using the ITemplate class. Specifically:
TemplateField tfCheck = new TemplateField();
          tfCheck.HeaderTemplate = new GridViewCheckBoxTemplate(DataControlRowType.Header,
          ((ArrayList)arrClass[0])[i].ToString());
          tfCheck.ItemTemplate = new GridViewCheckBoxTemplate(DataControlRowType.DataRow,((ArrayList)arrClass[0])[i].ToString());
          gvTest.Columns.Add(tfCheck);
         
Checkboxes are then added using the following code in the InstantiateIn fucnction of the class:
CheckBox cb = new CheckBox();
                  cb.CheckedChanged += new EventHandler(this.cb_CheckedChanged);
                  cb.AutoPostBack = true;
                  cb.DataBinding += new EventHandler(this.ctl_OnDataBinding);
                  container.Controls.Add(cb);
                 
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
LVL 22

Expert Comment

by:prairiedog
ID: 22636879
It will be a lot easier to add a TemplateField in GridView, then add a CheckBoxList control in the TemplateField, then bind the CheckBoxList with your data from DB.
0
 
LVL 1

Author Comment

by:rclint
ID: 22636917
I agree pprairiedog but my data isn't cut and dry like that.  I have to match five different pieces of data (instructor ID, curriculum, course, section, doc_ID) to determine whether the checkbox should be checked or not.  All five of those datafields have to exist in the table before the document can be considered turned on for a class.  It would be much easier if the data had a simple boolean field but it isn't possible in this case.

Thanks anyway though adn I will re-visit the checkboxlist too see if I didn't miss something.
0
 
LVL 1

Author Comment

by:rclint
ID: 22637033
NazoUK: I added in a !IsPostBack block in the page_load.  It caused all of my checkboxes to disappear.  I also verified that the CheckedChanged event will raise if the code in ctl_OnDataBinding is commented out.
0
 
LVL 22

Accepted Solution

by:
prairiedog earned 500 total points
ID: 22637794
>>>I have to match five different pieces of data (instructor ID, curriculum, course, section, doc_ID) to determine whether the checkbox should be checked or not.
You can definitely use GridView's RowDataBoudn to check those five fields than decide whether the check box needs be checked.
0
 
LVL 1

Author Comment

by:rclint
ID: 22654107
Putting the code into the rowdatabound function worked.  I am not sure why I didn't think about that on my own.  I had a bit of a disconnect between the row and cells relationship and was thinking that I had to do cell binding differently from row binding.

Thanks for the help.
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Tool Box 2 34
ADO.NET ENTITY DATA MODEL 3 30
Receiving a string from a WebService Push 21 36
SQL Login 17 38
ASP.Net to Oracle Connectivity Recently I had to develop an ASP.NET application connecting to an Oracle database.As I am doing it first time ,I had to solve several problems. This article will help to such developers  to develop an ASP.NET client…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.

919 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now