Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

c# - Repeater and Custom Control - Dynamically adding to the collection and retaining values

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...