1

It has been so long since I've used Web Forms I find myself not remembering most of the perks.

I have a user control that has a button, a repeater and the ItemTemplate property of the repeater is another user control.

<asp:Button runat="server" ID="btnAdd" CssClass="btn" Text="Add" OnClick="btnAdd_Click"/>
<br/>
<asp:Repeater runat="server" ID="rptrRequests">
    <ItemTemplate>
        <uc1:ucRequest ID="ucNewRequest" runat="server" />
    </ItemTemplate>
</asp:Repeater>

The idea is that when the user clicks on the Add button a new instance of the ucRequest is added to the collection. The code behind is as follows:

public partial class ucRequests : UserControl
{
    public List<ucRequest> requests
    {
        get
        {
            return (from RepeaterItem item in rptrRequests.Items 
                    select (ucRequest) (item.Controls[1])
                    ).ToList();
        }
        set
        {
            rptrRequests.DataSource = value;
            rptrRequests.DataBind();
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack) return;

        requests = new List<ucRequest>();
    }

    protected void btnAdd_Click(object sender, EventArgs e)
    {
        var reqs = requests;
        reqs.Add(new ucRequest());
        requests = reqs;
    }
}

After much googling I now remember that I should be binding the Repeater in the OnInit method in order for the ViewState to put the captured data of the controls within the ucRequest control on them between post backs but when I try to do that I will always have a single instance of the control on the Repeater since its Items collection is always empty.

How could I manage to do this?

Thanks in advance.

Sergio Romero
  • 6,477
  • 11
  • 41
  • 71

2 Answers2

2

You just need control ids in view state stead of entire control collection.

enter image description here

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeBehind="ucRequests.ascx.cs"
    Inherits="RepeaterWebApplication.ucRequests" %>
<asp:Button runat="server" ID="btnAdd" CssClass="btn" Text="Add" 
   OnClick="btnAdd_Click" />
<br /><asp:PlaceHolder runat="server" ID="PlaceHolder1"></asp:PlaceHolder>

<%@ Control Language="C#" AutoEventWireup="true" 
   CodeBehind="ucRequest.ascx.cs" 
   Inherits="RepeaterWebApplication.ucRequest" %>
<asp:TextBox runat="server" ID="TextBox1"></asp:TextBox>

private List<int> _controlIds;

private List<int> ControlIds
{
    get
    {
        if (_controlIds == null)
        {
            if (ViewState["ControlIds"] != null)
                _controlIds = (List<int>) ViewState["ControlIds"];
            else
                _controlIds = new List<int>();
        }
        return _controlIds;
    }
    set { ViewState["ControlIds"] = value; }
}

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        foreach (int id in ControlIds)
        {
            Control ctrl = Page.LoadControl("ucRequest.ascx");
            ctrl.ID = id.ToString();

            PlaceHolder1.Controls.Add(ctrl);
        }
    }
}

protected void btnAdd_Click(object sender, EventArgs e)
{
    var reqs = ControlIds;
    int id = ControlIds.Count + 1;

    reqs.Add(id);
    ControlIds = reqs;

    Control ctrl = Page.LoadControl("ucRequest.ascx");
    ctrl.ID = id.ToString();

    PlaceHolder1.Controls.Add(ctrl);
}
Win
  • 61,100
  • 13
  • 102
  • 181
0

Try to get the ucRequests during the OnItemDatabound event, at that point you can edit the content of itemtemplate of the repeater. You can get there after the postback caused by the click on the add button. Here's a sample with a similar scenario

Giorgio Minardi
  • 2,765
  • 1
  • 15
  • 11