?
Solved

Dynamic GridView w/ checkboxes not executing CheckedChanged Event

Posted on 2008-10-03
9
Medium Priority
?
7,453 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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

Quiz: What Do These Organizations Have In Common?

Hint: Their teams ended up taking quizzes, too.

Question has a verified solution.

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

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…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

801 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