Solved

Dynamic GridView w/ checkboxes not executing CheckedChanged Event

Posted on 2008-10-03
9
7,377 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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

747 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

14 Experts available now in Live!

Get 1:1 Help Now