Here is my custom control code:
namespace MyControlNameSpace
{
public class MyControlItemCommandEventArgs : CommandEventArgs
{
private MyControlItem _item;
private object _commandSource;
public MyControlItemCommandEventArgs(MyControlItem item, object commandSource, CommandEventArgs cea) : base(cea)
{
_item = item;
_commandSource = commandSource;
}
public MyControlItem Item { get{ return _item; } }
public object CommandSource { get{ return _commandSource; } }
}
public class MyControlItem : Control, IDataItemContainer
{
public MyControlItem(object dataItem, int index)
{
_dataItem = dataItem;
_dataItemIndex = _displayIndex = index;
}
private readonly object _dataItem;
private readonly int _dataItemIndex;
private readonly int _displayIndex;
public object DataItem { get { return _dataItem; } }
public int DataItemIndex { get { return _dataItemIndex; } }
public int DisplayIndex { get { return _displayIndex; } }
protected override bool OnBubbleEvent(object source, EventArgs args)
{
if (args is CommandEventArgs)
{
var e = new MyControlItemCommandEventArgs(this, source, (CommandEventArgs)args);
base.RaiseBubbleEvent(this, e);
return true;
}
return false;
}
}
public delegate void ItemEventHandler(object sender, MyControlItemCommandEventArgs e);
[DefaultProperty("Text")]
[ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>")]
public class MyControl : CompositeDataBoundControl, IPrivilage
{
public event ItemEventHandler ItemCommand;
protected virtual void OnItemCommand(MyControlItemCommandEventArgs e)
{
if (ItemCommand != null)
ItemCommand(this, e);
}
protected override bool OnBubbleEvent(object source, EventArgs args)
{
// only bother bubbling appropriate events
if (args is MyControlItemCommandEventArgs)
{
OnItemCommand((MyControlItemCommandEventArgs)args);
return true;
}
return false;
}
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
{
// here I'm adding some controls like buttons and other
// Iterate for ItemTemplate
foreach (object dataItem in dataSource)
{
if (ItemTemplate != null)
{
// create instance of MyControlItem control
var item = new MyControlItem(dataItem, count++);
// instantiate in new item object
ItemTemplate.InstantiateIn(item);
// add item to Controls collection
Controls.Add(item);
// need to support <%# %> expressions
item.DataBind();
}
}
// some code here
}
}
In .aspx page:
protected void Page_Load(object sender, EventArgs e)
{
// if it's not post back then get the data and assign to MyControl DataSource property
if(!IsPostBack)
GetData();
}
protected void MyControl1_OnItemCommand(object sender, MyControlItemCommandEventArgs e)
{
var x = e.DataItem;
// x here is always null;
}
As you can see I can't get e.DataItem when OnItemCommand event because it's always null.
I tried to remove if(!IsPostBack) in Page_Load so that every time page load datasource assigned, but this is not right, I should be able to not assigning datasource if it's PostBack like in Asp.Net Repeater control.
Any Idea how to do it?
The
OnItemCommandevent is raised on post-back. At that point, if theCompositeDataBoundControlhasViewStateenabled, it will recreate the child controls without querying the database. YourCreateChildControlsmethod will be called withdataBindingset tofalse, and thedataSourcewill be an enumerable sequence ofnullobjects which serve as placeholders for the actual data.You'll get the same behaviour in any data-bound control. If you try the same thing with a
Repeater, you'll see that thee.Item.DataItemisnullin theItemCommandevent.