mebarron
asked on
VS .NET C# WebForm Project with DataGrid - DataBinding problem
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 .TemplateC olumn
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
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
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
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
ASKER
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 .
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 .
ASKER
Dear seeflat, why is the ViewState preferred to Session for storing
UI elements?
Thanks, Mark
UI elements?
Thanks, Mark
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.
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.
ASKER
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"
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.Horizon
//Subscribe to two events because you will be doing work in the WebForm code
checkCol.CheckedChanged +=
new EventHandler(this.CheckBox
checkCol.DataBinding +=
new EventHandler(this.CheckBox
DataGrid1.Columns.Add(chec
--- 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.Horizon
checkCol.CheckedChanged +=
new EventHandler(this.CheckBox
checkCol.DataBinding +=
new EventHandler(this.CheckBox
DataGrid1.Columns.Add(chec
if (! IsPostBack)
{
sqlDataAdapterIdContract.F
dataViewIdContract = new DataView(dsIdContract1.Tab
Session["IdContractView"] = dataViewIdContract;
Session["IdContractTable"]
}
sqlDataAdapterIdNameContac
DataGrid1.DataBind();
}
\\\ end page_load
In WebForm1.aspx.cs handlers(2) follow
protected void CheckBox_DataBinding(objec
{
DataTable IdContractTable = (DataTable)Session["IdCont
if(IdContractTable != null)
{
CheckBox box = (CheckBox) sender;
DataGridItem dgi = (DataGridItem) box.NamingContainer;
string sId = dgi.Cells[0].Text ;
DataRow sessionRow = IdContractTable.Rows.Find(
bool bChecked = (bool)sessionRow["contract
box.Checked = (bool)sessionRow["contract
}
}
protected void CheckBox_CheckedChanged(ob
{
DataTable table = (DataTable)Session["IdCont
dataViewIdContract = (DataView)Session["IdContr
CheckBox box = (CheckBox) sender;
DataGridItem dgi = (DataGridItem) box.NamingContainer;
string sID = dgi.Cells[0].Text;//dataVi
dataViewIdContract.Sort = "au_id";
int nID = dataViewIdContract.Find(sI
DataRow dr = table.Rows[nID];
dr["contract"]= box.Checked; // change value in local Checked_Table
Session["IdContractTable"]
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:tru
}
/// <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(Co
{
CheckBox box = new CheckBox();
box.DataBinding += new EventHandler(this.BindData
box.AutoPostBack = autoPostBack;
box.CheckedChanged += new EventHandler(this.OnCheckC
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;
}
}