Solved

Dynamic GridView w/ checkboxes not executing CheckedChanged Event

Posted on 2008-10-03
9
7,431 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

 
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
 
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

Containers & Docker to Create a Powerful Team

Containers are an incredibly powerful technology that can provide you and/or your engineering team with huge productivity gains. Using containers, you can deploy, back up, replicate, and move apps and their dependencies quickly and easily.

Question has a verified solution.

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

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

691 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