Search code examples
c#asp.netuser-controlsrepeater

Calling a method in parent page from a user control residing inside a repeater control


I followed a number of other question to try to solve this problem but they don't seem to apply to my case. This is an example.

In my case, an instance of the user control is being loaded multiple times in a repeater and I am suspecting this has something to do with the problem I have.

I am attaching the event to each instance of the user control using this method.

  protected void rptPosts_ItemDataBound(object sender, RepeaterItemEventArgs e)
  {
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
      DataRowView MyRow = (DataRowView)e.Item.DataItem;
      Post MyPost = (Post)e.Item.FindControl("Post");

      MyPost.UserControlButtonClicked += new EventHandler(MyPost_UserControlButtonClicked);

      MyPost.LoadPost(MyRow);
    }
  }

  private void MyPost_UserControlButtonClicked(object sender, EventArgs e)
  {
    // reload repeater items
  }

Inside the user control code behind I put this code:

  public event EventHandler UserControlButtonClicked;

  private void OnUserControlButtonClick()
  {
    if (UserControlButtonClicked != null)
    {
      UserControlButtonClicked(this, EventArgs.Empty);
    }
  }

And in the button inside the user control (that is supposed to trigger the page method) I put this:

  protected void lnkDelete_Click(object sender, EventArgs e)
  {
    // Code to delete record //

    OnUserControlButtonClick();
  }

The problem seems to be that if (UserControlButtonClicked != null) seems to always return false and therefore UserControlButtonClicked(this, EventArgs.Empty); is never executed.


Solution

  • You need to hook the event up on OnItemCreated. Othervise if you post the page it will be gone. So I would expect that it will look something like this:

    protected void rptPosts_ItemCreated(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Post MyPost = (Post)e.Item.FindControl("Post");
            MyPost.UserControlButtonClicked += new EventHandler(MyPost_UserControlButtonClicked);
        }
    }
    

    And then in ItemDataBound you do not really need to hook the event up. So it will look like this:

    protected void rptPosts_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
          DataRowView MyRow = (DataRowView)e.Item.DataItem;
          Post MyPost = (Post)e.Item.FindControl("Post");
          MyPost.LoadPost(MyRow);
        }
    }
    

    In ItemDataBound you still need to load the post. I would not suggest doing that in ItemCreated. Because that would mean that you will load the posts every time you create the item. Which is not what you want

    Reference: