Solved

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

Posted on 2003-12-09
6
6,768 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
[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
  • 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
Industry Leaders: 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!

 

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

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

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

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
There's a multitude of different network monitoring solutions out there, and you're probably wondering what makes NetCrunch so special. It's completely agentless, but does let you create an agent, if you desire. It offers powerful scalability …
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

719 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