Почему DataItem в моем пользовательском элементе управления с привязкой к данным шаблона имеет значение null в событии ItemCommand?
Вот мой собственный контрольный код:
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
}
}
На странице.aspx:
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;
}
Как вы можете видеть, я не могу получить e.DataItem, когда событие OnItemCommand, потому что оно всегда нулевое.
Я пытался удалить if(!IsPostBack)
в Page_Load
так что каждый раз при загрузке страницы назначается источник данных, но это неправильно, я должен иметь возможность не назначать источник данных, если он PostBack
как в Asp.Net Repeater
контроль.
Любая идея, как это сделать?
1 ответ
OnItemCommand
событие поднято на пост-обратно. В этот момент, если CompositeDataBoundControl
имеет ViewState
включен, он будет воссоздавать дочерние элементы управления, не запрашивая базу данных. Ваш CreateChildControls
метод будет вызван с dataBinding
установлен в false
и dataSource
будет перечисляемая последовательность null
объекты, которые служат заполнителями для фактических данных.
Вы получите такое же поведение в любом элементе управления с привязкой к данным. Если вы попробуете то же самое с Repeater
вы увидите, что e.Item.DataItem
является null
в ItemCommand
событие.