Solved

VS .NET C# WebForm Project with DataGrid - DataBinding problem

Posted on 2003-12-09
6
6,735 Views
Last Modified: 2010-08-05
Background:
 VS .NET WebForm Project. Form has DataGrid. DataGrid has five columns
 Four of the columns including ID are present in a DataBase table.
 The fifth column is a Template Column. This column is :
       class CheckBoxColumn :System.Web.UI.WebControls.TemplateColumn
 The CheckBoxColumn contains an object of the class CheckBoxItem :
  class CheckBoxItem : ITemplate
 The CheckBoxItem instantiates a CheckBox object.
 Note: AutoPostBack is used in this object, such
 that PostBack takes place at each Click on the CheckBox obj.
 
 By subscribing to events, the status of CheckBox.Checked can be
 maintained,from code in FormName.aspx.cs --- so long
 as no paging takes place.
 
 The DataGrid is paged. When paging away from and then back to a page,
 the status of the Checked properties is lost.
 
 The meaning of the CheckBox.Checked is not meaningful in the
 DataBase Table and can not be persisted there -it has User
 specific meaning. The meaning
 is relative to the session. The status of the checkboxes can
 be persisted in , say a Session table,which is updated each time
 there is a CheckedChanged event.
 Question:
  How and where do i merge the table from the DataBase with the Session table of
  two columns (ID, and a boolean for the Checked status), such that
  the DataBind() in Page_Load will cause the correct display of the
  column #5. I find that the CheckChange event is raised after the
  Page_Load() runs. Or is there a better approach?
 
  Many Thanks
 
0
Comment
Question by:mebarron
  • 3
  • 3
6 Comments
 
LVL 5

Accepted Solution

by:
seeflat earned 250 total points
ID: 9914069
I'm not totally clear on your question, but I'll give a suggestion based on my perception of what you're asking.
I've run into similiar issues with datagrids, paging, and persistance.

What I've done is written a class the inherits from CollectionBase and marked it as serializable.
I fill the collection with the current state of the checkboxes and associated Ids in the DataGrid based on some sort of event; in your case it sounds like you would use the CheckBox event and the DataGrid paging event.
Then between postbacks I dump this CollectionBase into the Viewstate and read it back into my collection on PageLoad, then I just use this collection in the DataGrids ItemDataBound event to render the appropriate state of the checkboxes.

HTH
0
 

Author Comment

by:mebarron
ID: 9922201
I finally got it working!
I am not easily offended, please criticize. This works
but I suspect there is a much better easier way !!!!
Class files can be found at : http://www.codeproject.com/aspnet/datagrid_checkbox.asp

These classes are CheckBoxColumn and CheckItem;
I altered CheckItem.cs and it is at bottom.
Using the discussion at the website, I build a program
that failed to maintain checkbox state between Paging events.
Now it does.
The third of three rows in DataGrid is added programmatically
Design time sees only two columns.
Using the da.Fill() data from the DataBase pubs.authors fills table for Grid.
This table includes id, au_lname and a boolean row 'contract' which is
associated with the state of the CheckBox. A Session
Table is maintained. Initially the Session table , which has
two columns (ID and contract) has its data from
the DataBase.  The Session table , namely Session["IdContractTable"]
gets adjusted at each CheckBox.CheckedChanged event.

DataBinding use the data from ,Session["IdContractTable"] to
set .Checked for the CheckBoxs

In the form I added a CheckBoxColumn in Page_Load() :
               CheckBoxColumn checkCol = new CheckBoxColumn(true);// param==ImmedPostback
                  checkCol.HeaderText = "Contrac";
                  checkCol.DataField = "contract";
                  checkCol.ItemStyle.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center ;
//Subscribe to two events because you will be doing work in the WebForm code
                  checkCol.CheckedChanged +=
                        new EventHandler(this.CheckBox_CheckedChanged);
                  checkCol.DataBinding +=
                        new EventHandler(this.CheckBox_DataBinding);
                  DataGrid1.Columns.Add(checkCol);
--- begin entire page_load()
            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  CheckBoxColumn checkCol = new CheckBoxColumn(true);// param==ImmedPostback
                  checkCol.HeaderText = "Contrac";
                  checkCol.DataField = "contract";
                  
                  checkCol.ItemStyle.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center ;
                  checkCol.CheckedChanged +=
                        new EventHandler(this.CheckBox_CheckedChanged);
                  checkCol.DataBinding +=
                        new EventHandler(this.CheckBox_DataBinding);
                  DataGrid1.Columns.Add(checkCol);
                  if (! IsPostBack)
                  {
                        sqlDataAdapterIdContract.Fill(dsIdContract1,"tblIdContract");//"two columns"
                        dataViewIdContract = new DataView(dsIdContract1.Tables["tblIdContract"]);
                        Session["IdContractView"] = dataViewIdContract;
                        Session["IdContractTable"] = dsIdContract1.Tables["tblIdContract"];
                  }
                  sqlDataAdapterIdNameContact.Fill(dsIdNameContact1);/*three columns*/
                  DataGrid1.DataBind();
            }


\\\ end page_load
In WebForm1.aspx.cs handlers(2) follow

            protected void CheckBox_DataBinding(object sender, System.EventArgs e)
            {
                  DataTable IdContractTable = (DataTable)Session["IdContractTable"];
                  if(IdContractTable != null)
                  {
                        CheckBox box = (CheckBox) sender;
                        DataGridItem dgi = (DataGridItem) box.NamingContainer;
                        string sId = dgi.Cells[0].Text ;
                        DataRow sessionRow = IdContractTable.Rows.Find(sId);
                        bool bChecked = (bool)sessionRow["contract"];
                        box.Checked = (bool)sessionRow["contract"];
                  }
            }
            protected void CheckBox_CheckedChanged(object sender, System.EventArgs e)
            {
                  DataTable table = (DataTable)Session["IdContractTable"];
                  dataViewIdContract = (DataView)Session["IdContractView"];
                  CheckBox box = (CheckBox) sender;
                  DataGridItem dgi = (DataGridItem) box.NamingContainer;
                  string sID = dgi.Cells[0].Text;//dataViewIdContract.Find((( (Button)dgi.Cells[0].Controls[0]).Text);
                  dataViewIdContract.Sort = "au_id";
                  int nID = dataViewIdContract.Find(sID);//"238-95-7766"
                  DataRow dr = table.Rows[nID];
                  dr["contract"]= box.Checked; // change value in local Checked_Table
                  Session["IdContractTable"] = table;
                  Session["IdContractView"] = new DataView(table);
            }
            
            I altered the CheckItem class somewhat it follows
            ///////////checkItem begins//////////////////
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

namespace SwapIt
{
      internal class CheckBoxItem : ITemplate
      {
            /// <summary>
            /// The CheckBoxItem constructor
            /// </summary>
            /// <param name="editable">true if the item is to be in its editable state, false for the item to be disabled.</param>
            public CheckBoxItem(bool editable)
            {
                  readOnly = (editable==true)?false:true;
            }
            /// <summary>
            /// Instantiates the CheckBox that we wish to represent in this column.
            /// </summary>
            /// <param name="container">The container into which the control or controls are added.</param>
            void ITemplate.InstantiateIn(Control container)
            {
                  CheckBox box = new CheckBox();
                  box.DataBinding += new EventHandler(this.BindData);
                  box.AutoPostBack = autoPostBack;
                  box.CheckedChanged += new EventHandler(this.OnCheckChanged);
                  container.Controls.Add(box);
                  box.EnableViewState = true;
            }
            /// <summary>
            /// Our CheckChanged event
            /// </summary>
            public event EventHandler CheckedChanged;// eventname==CHeckedChanged
                                                                        // subscriber method is invoked
                                                                        // through delegate , here DelType==EH
            public event EventHandler DataBinding;
            /// <summary>
            /// This is a common handler for all the Checkboxes.
            /// </summary>
            /// <param name="sender">The raiser of this event a CheckBox.</param>
            /// <param name="e">A System.EventArgs that contains the event data.</param>
            private void OnCheckChanged(object sender, EventArgs e)
            {
                  CheckBox box = (CheckBox) sender;
                  if (CheckedChanged != null)
                  {
                        CheckedChanged(sender, e);
                        box.DataBind();
                  }
                  
            /***
                  if (data.Length>0)
                  {
                        switch (t.ToString())
                        {
                              case "System.Boolean":
                                    if (( data == "True") || (data == "true"))
                                    {
                                          box.Checked = true;
                                          if(DataBinding != null)
                                                DataBinding(sender,e); //Let form set Data in DataGrid
                                    }
                                    break;
                              default:
                                    break;
                        }
                  }
                  ***/
                  
            }
            /// <summary>
            /// The internal storage for which DataField we are going to represent.
            /// </summary>
            private string dataField;
            /// <summary>
            /// Used to set the DataField that we wish to represent with this CheckBox.
            /// </summary>
            public string DataField
            {
                  get
                  {
                        return dataField;
                  }
                  set
                  {
                        dataField=value;
                  }
            }

            /// <summary>
            /// The internal storage for the AutoPostback flag.
            /// </summary>
            private bool autoPostBack=false;

            /// <summary>
            /// Set the AutoPostBack flag. If this is true then each time a CheckBox is clicked
            /// in the Column that contains this item then an event is raised on the server.
            /// </summary>
            public bool AutoPostBack
            {
                  set
                  {
                        autoPostBack = value;
                  }
                  get
                  {
                        return autoPostBack;
                  }
            }

            /// <summary>
            /// Handler for the DataBinding event where we bind the data for a specific row
            /// to the CheckBox.
            /// </summary>
            /// <param name="sender">The raiser of the event.</param>
            /// <param name="e">A System.EventArgs that contains the event data.</param>
            private void BindData(object sender, EventArgs e)
            {
                  if(DataBinding != null)
                        DataBinding(sender,e); //Let form set Data in DataGrid
                                                                                    
            }

            /// <summary>
            /// Internal storage for the readOnly flag.
            /// </summary>
            private bool readOnly = true;
      }
}
0
 
LVL 5

Expert Comment

by:seeflat
ID: 9922602
In my opinion, it's more complicated then what I suggested...
However, if you understand everything that is going on, and are comfortable with it; go for it.

Also, I try to stay away from using the Session object for UI elements, thats what the ViewState is for. It would not be that difficult for you to switch using the Session for the ViewState.

There are many ways to solve a problem, congrats on solving your own.

seeflat
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:mebarron
ID: 9925622
I realize that this may confuse some. This is a
demo to have one column with data that is persisted
in a Session object and not in a DB table. In using
pubs DB, I realize now, that it may be puzzling
why I want to persist the boolean 'contract'
values for authors in the Session. This would
make no sense. I have and application where
the CheckBox column data relates to whether
a user want to purchase a used magazine offered
for sale. This data can not be stored in a single
db table for multiple users. Its meaning is relative
to the Session only .
0
 

Author Comment

by:mebarron
ID: 9925644
Dear seeflat, why is the ViewState preferred to Session for storing
UI elements?
 Thanks, Mark
0
 
LVL 5

Expert Comment

by:seeflat
ID: 9925698
The ViewState is actually stored in the page itself, as a hidden form field where the data is Base64 encoded (View source on an ASPX and check it out). This makes the site much more scalable, as you aren't dependent on Session objects. For instance, in a Web Farm environment. The Session object is a powerful thing, but should only be used when justified.

However, .NET does provide a way to use SQL Server as the Session store, but it should be used for things that are truly session related. The ViewState is supposed to used for exactly that; storing state data related to the view(UI).

In reading your last comment I see that you have a pretty good justification for using the Session object.

So rock on, and good luck with future dev.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…

910 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

22 Experts available now in Live!

Get 1:1 Help Now