Почему 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 событие.

Другие вопросы по тегам