S
Steve
I'm trying to implement databinding on a composite control and I'm getting an
error with the data when I change the DataSource. The first time I set the
DataSource and call DataBind() everything works fine, but when I set the
DataSource to a new value (DataTable) and then call DataBind again, I get
some strange results from the command events of some embedded ImageButton
controls... althought the data appears to be displayed correctly, the
CommandName and CommandArguement values are offset by 1 row. What's worse,
is the error goes away after I post-back a few times (which restores the data
from the ViewState). This is driving me nuts. It seems like the error is
somehow related to the order of operations surrounding the post-back,
EnsureChildControls (in OnLoad), and then calling DataBind (which creates the
controls again).
I'm attaching the full class, if anyone is willing to be of service of give
it a look. I would appreciate any help greatly.
//class code start here:
using System;
using System.Data;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Summary description for ItemList.
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:ItemList runat=server></{0}:ItemList>")]
public class ItemList : System.Web.UI.WebControls.WebControl
{
private bool _isGrid = true;
private DataTable _dataTable = null;
#region public properties/methods/overrides
public ItemList() : base(){}
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
if( this.Page.IsPostBack )
{
EnsureChildControls();
}
}
public bool RenderGrid
{
get
{
return _isGrid;
}
set
{
_isGrid = value;
}
}
override public object DataSource
{
set
{
_dataTable = (DataTable)value;
ViewState["data"] = value;
}
}
public override void DataBind()
{
CreateControlHierarchy();
}
protected override void CreateChildControls()
{
CreateControlHierarchy();
}
private void CreateControlHierarchy()
{
Controls.Clear();
ClearChildViewState();
if( !IsTrackingViewState ){ TrackViewState(); }
if( _isGrid )
{
if( _dataTable == null )
{
CreateItemGrid( (DataTable)ViewState["data"] );
}
else
{
CreateItemGrid( _dataTable );
}
}
else
{
}
ChildControlsCreated = true;
}
#endregion
#region CreateItemGrid
private void CreateItemGrid(DataTable dt)
{
Table t = new Table();
t.CssClass = "reportTable";
TableRow r = new TableRow();
TableCell cl = new TableCell();
r = new TableRow();
int c = 1;
for( ; c<dt.Columns.Count; c++ )
{
r.Cells.Add( AddGridHdrFtrCell( dt.Columns[c].ColumnName, true ) );
}
r.Cells.Add( AddGridHdrFtrCell( " ", true ) );
r.Cells.Add( AddGridHdrFtrCell( " ", true ) );
t.Rows.Add( r );
for( int row=0; row<dt.Rows.Count; row++ )
{
r = new TableRow();
c = 1;
for( ; c<dt.Columns.Count; c++ )
{
r.Cells.Add( AddGridDataCell(
dt.Rows[row][dt.Columns[c].ColumnName].ToString(), row ) );
}
r.Cells.Add( AddGridLinkButtonCell( dt.Rows[row]["itmPk"].ToString(),
true, row) );
r.Cells.Add( AddGridLinkButtonCell( dt.Rows[row]["itmPk"].ToString(),
false, row) );
t.Rows.Add( r );
}
r = new TableRow();
cl = new TableCell();
cl.ColumnSpan = dt.Columns.Count + 2;
cl.Text = string.Format( "{0} items", dt.Rows.Count );
cl.CssClass = "reportFooter";
r.Cells.Add( cl );
t.Rows.Add( r );
r = new TableRow();
cl = new TableCell();
cl.ColumnSpan = dt.Columns.Count + 2;
cl.Text = " ";
cl.CssClass = "reportItem";
r.Cells.Add( cl );
t.Rows.Add( r );
this.Controls.Add( t );
}
private TableCell AddGridHdrFtrCell(string text, bool hdr)
{
TableCell c = new TableCell();
c.Text = text;
c.CssClass = hdr ? "reportHeader" : "reportFooter";
return c;
}
private TableCell AddGridDataCell(string text, int i)
{
TableCell c = new TableCell();
c.Text = text;
c.CssClass = (i+1)%2==0 ? "reportItem" : "reportAltItem";
return c;
}
private TableCell AddGridLinkButtonCell(string pk, bool view, int i)
{
ImageButton l = new ImageButton();
l.Visible = visible;
l.CommandArgument = pk;
//l.Command += new CommandEventHandler(ImageButton_Command);
if( view )
{
l.ImageUrl = "../images/rec_view.gif";
l.AlternateText = "View detail " + pk;
l.CommandName = "view";
}
else
{
l.ImageUrl = "../images/rec_edit.gif";
l.AlternateText = "Edit this item " + pk;
l.CommandName = "edit";
}
TableCell c = new TableCell();
c.Controls.Add( l );
c.CssClass = (i+1)%2==0 ? "reportItem" : "reportAltItem";
return c;
}
protected override bool OnBubbleEvent(object source, EventArgs ea)
{
bool handled = false;
if( ea is CommandEventArgs )
{
CommandEventArgs e = (CommandEventArgs)ea;
switch( e.CommandName.ToLower() )
{
case "view":
{
OnRecordAction( new RecordActionEventArgs(
e.CommandArgument.ToString(), RecordMode.Select ) );
handled = true;
break;
}
case "edit":
{
OnRecordAction( new RecordActionEventArgs(
e.CommandArgument.ToString(), RecordMode.Update ) );
handled = true;
break;
}
}
}
return handled;
}
private void ImageButton_Command(object sender, CommandEventArgs e)
{
}
#endregion
}
}
error with the data when I change the DataSource. The first time I set the
DataSource and call DataBind() everything works fine, but when I set the
DataSource to a new value (DataTable) and then call DataBind again, I get
some strange results from the command events of some embedded ImageButton
controls... althought the data appears to be displayed correctly, the
CommandName and CommandArguement values are offset by 1 row. What's worse,
is the error goes away after I post-back a few times (which restores the data
from the ViewState). This is driving me nuts. It seems like the error is
somehow related to the order of operations surrounding the post-back,
EnsureChildControls (in OnLoad), and then calling DataBind (which creates the
controls again).
I'm attaching the full class, if anyone is willing to be of service of give
it a look. I would appreciate any help greatly.
//class code start here:
using System;
using System.Data;
using System.Collections;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace System.Web.UI.WebControls
{
/// <summary>
/// Summary description for ItemList.
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:ItemList runat=server></{0}:ItemList>")]
public class ItemList : System.Web.UI.WebControls.WebControl
{
private bool _isGrid = true;
private DataTable _dataTable = null;
#region public properties/methods/overrides
public ItemList() : base(){}
protected override void OnLoad(EventArgs e)
{
base.OnLoad (e);
if( this.Page.IsPostBack )
{
EnsureChildControls();
}
}
public bool RenderGrid
{
get
{
return _isGrid;
}
set
{
_isGrid = value;
}
}
override public object DataSource
{
set
{
_dataTable = (DataTable)value;
ViewState["data"] = value;
}
}
public override void DataBind()
{
CreateControlHierarchy();
}
protected override void CreateChildControls()
{
CreateControlHierarchy();
}
private void CreateControlHierarchy()
{
Controls.Clear();
ClearChildViewState();
if( !IsTrackingViewState ){ TrackViewState(); }
if( _isGrid )
{
if( _dataTable == null )
{
CreateItemGrid( (DataTable)ViewState["data"] );
}
else
{
CreateItemGrid( _dataTable );
}
}
else
{
}
ChildControlsCreated = true;
}
#endregion
#region CreateItemGrid
private void CreateItemGrid(DataTable dt)
{
Table t = new Table();
t.CssClass = "reportTable";
TableRow r = new TableRow();
TableCell cl = new TableCell();
r = new TableRow();
int c = 1;
for( ; c<dt.Columns.Count; c++ )
{
r.Cells.Add( AddGridHdrFtrCell( dt.Columns[c].ColumnName, true ) );
}
r.Cells.Add( AddGridHdrFtrCell( " ", true ) );
r.Cells.Add( AddGridHdrFtrCell( " ", true ) );
t.Rows.Add( r );
for( int row=0; row<dt.Rows.Count; row++ )
{
r = new TableRow();
c = 1;
for( ; c<dt.Columns.Count; c++ )
{
r.Cells.Add( AddGridDataCell(
dt.Rows[row][dt.Columns[c].ColumnName].ToString(), row ) );
}
r.Cells.Add( AddGridLinkButtonCell( dt.Rows[row]["itmPk"].ToString(),
true, row) );
r.Cells.Add( AddGridLinkButtonCell( dt.Rows[row]["itmPk"].ToString(),
false, row) );
t.Rows.Add( r );
}
r = new TableRow();
cl = new TableCell();
cl.ColumnSpan = dt.Columns.Count + 2;
cl.Text = string.Format( "{0} items", dt.Rows.Count );
cl.CssClass = "reportFooter";
r.Cells.Add( cl );
t.Rows.Add( r );
r = new TableRow();
cl = new TableCell();
cl.ColumnSpan = dt.Columns.Count + 2;
cl.Text = " ";
cl.CssClass = "reportItem";
r.Cells.Add( cl );
t.Rows.Add( r );
this.Controls.Add( t );
}
private TableCell AddGridHdrFtrCell(string text, bool hdr)
{
TableCell c = new TableCell();
c.Text = text;
c.CssClass = hdr ? "reportHeader" : "reportFooter";
return c;
}
private TableCell AddGridDataCell(string text, int i)
{
TableCell c = new TableCell();
c.Text = text;
c.CssClass = (i+1)%2==0 ? "reportItem" : "reportAltItem";
return c;
}
private TableCell AddGridLinkButtonCell(string pk, bool view, int i)
{
ImageButton l = new ImageButton();
l.Visible = visible;
l.CommandArgument = pk;
//l.Command += new CommandEventHandler(ImageButton_Command);
if( view )
{
l.ImageUrl = "../images/rec_view.gif";
l.AlternateText = "View detail " + pk;
l.CommandName = "view";
}
else
{
l.ImageUrl = "../images/rec_edit.gif";
l.AlternateText = "Edit this item " + pk;
l.CommandName = "edit";
}
TableCell c = new TableCell();
c.Controls.Add( l );
c.CssClass = (i+1)%2==0 ? "reportItem" : "reportAltItem";
return c;
}
protected override bool OnBubbleEvent(object source, EventArgs ea)
{
bool handled = false;
if( ea is CommandEventArgs )
{
CommandEventArgs e = (CommandEventArgs)ea;
switch( e.CommandName.ToLower() )
{
case "view":
{
OnRecordAction( new RecordActionEventArgs(
e.CommandArgument.ToString(), RecordMode.Select ) );
handled = true;
break;
}
case "edit":
{
OnRecordAction( new RecordActionEventArgs(
e.CommandArgument.ToString(), RecordMode.Update ) );
handled = true;
break;
}
}
}
return handled;
}
private void ImageButton_Command(object sender, CommandEventArgs e)
{
}
#endregion
}
}