0
votes

I have a customer user control, AddressControl.ascx, which is contained inside a repeater control. When my page first loads, everything seems to be working fine, and my repeater is creating two items for the dummy addresses populated in the Page_Load event. However, when I click on Add Address button, a 3rd repeater item is added, but now all my other repeater items are empty (i.e. all the fields on the screen become empty).

While debugging this, I noticed that on first load, AddressControl's Page_Load event has the address object. However, when we come to Page_Load after clicking on the Add Address button, the address object is null.

*Note: The goal of the Add Address button is for an empty set of controls to appear to allow the user to enter a new address.

Any help is greatly appreciated.

AddressControl.ascx

public partial class AddressControl : System.Web.UI.UserControl
    {
        public Address address { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (address != null)
            {
                txtStreet1.Text = address.Address1;
                txtStreet2.Text = address.Address2;
                txtCity.Text = address.City;
                cboRegion.SelectedIndex = 2;
                txtPostalCode.Text = address.PostalCode;
            }
        }
    }

Default.aspx

<asp:Repeater ID="AddrRepeater" runat="server" OnItemDataBound="AddrRepeater_ItemDataBound">
    <ItemTemplate>
        <uc1:AddressControl runat="server" id="ctlAddress" />
    </ItemTemplate>
</asp:Repeater>
<asp:Button ID="btnAdd" runat="server" text="Add Address" OnClick="btnAdd_Click" />

Default.aspx.cs

public partial class Default : System.Web.UI.Page
{
    public List<Address> Addresses
    {
        get
        {
            var addresses = HttpContext.Current.Session["addressList"] as List<Address>;
            if (addresses == null)
            {
                addresses = new List<Address>();
                HttpContext.Current.Session["addressList"] = addresses;
            }
            return addresses;
        }
        set
        {
            HttpContext.Current.Session["addressList"] = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Addresses = new List<Address>()
            {
                new Address { Address1 = "123 Main St", Address2 = "", City = "New York", State = "NY", PostalCode = "10001" },
                new Address { Address1 = "555 Fake St", Address2 = "", City = "New York", State = "CA", PostalCode = "91367" }
            };

            AddrRepeater.DataSource = Addresses;
            AddrRepeater.DataBind();
        }
    }

    protected void AddrRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            var address = e.Item.DataItem as Address;

            var addrCtl = e.Item.FindControl("ctlAddress") as AddressControl;
            addrCtl.address = address;
        }
    }

    protected void btnAdd_Click(object sender, EventArgs e)
    {
        Address newAddress = new Address();
        Addresses.Add(newAddress);

        AddrRepeater.DataSource = Addresses;
        AddrRepeater.DataBind();
    }
}
2

2 Answers

0
votes

you will need to implement a viewstate track if you want the control to retain the values after postback

    public Address address
    {
        get
        {
            object o = ViewState["address"];
            return o == null ? null : (Address)o;
        }
        set {
            ViewState["address"] = value;
        }
     }
0
votes

I figured it out.

It's all about the Page Event Life Cycle. As you can see, I was trying to access the Address object and populate the textbox fields in the PageLoad event. This is wrong.

Here's the order of events firing:

1. Default.aspx.cs - Page_Load
2. AddressControl.ascx.cs - Page_Load // Address object is still null here because it hasn't been assigned a value from the Default.aspx.cs's ItemDataBound event.
3. Default.aspx.cs - ItemDataBound // Address assigned here
4. AddressControl.ascx.cs - OnPreRender // Here the Address object is NOT null.

Event if my Address object in AddressControl.ascx.cs was implemented using a ViewState, it wouldn't have helped because in step 2 above, it would be referencing an old object from the previous PostBack.