Solved

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

Posted on 2003-12-09
6
6,731 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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
c#.net application + check if already running 5 49
How do I get the id from URL? 19 48
C# Export DataGridView 4 41
Create XML 5 35
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

744 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

11 Experts available now in Live!

Get 1:1 Help Now