Hi All,
I have a control I've created, which can have a number of child controls - also user controls - stored as an ArrayList, which can be added wither a design time or programmatically.
My problem is when I add to the list programmatically, it doesn't persist them. So if I add 3 child controls in step 1 of a wizard, with the aim that those three will be visible inside the parent in step 3, what happens is that the parent has no child controls and the item count is 0.
Can anyone help? Thanks in advance.
Code:
Parent Control Markup:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Beneficiaries.ascx.cs" Inherits="Beneficiaries" %>
<%@ Register TagPrefix="gm" TagName="beneficiaryInput" src="~/beneficiaryInput.ascx" %>
<div runat="server" id="container">
</div>Parent Control Code:
1 using System;Child Control Markup:
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.ComponentModel.Design;
6 using System.Drawing.Design;
7 using System.Text;
8 using System.Web;
9 using System.Web.UI;
10 using System.Web.UI.WebControls;
11
12 [DefaultEvent("SelectedIndexChanged"),
13 Designer("System.Web.UI.Design.WebControls.ListControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
14 ParseChildren(true, "Items"), ControlValueProperty("SelectedValue"),
15 DataBindingHandler("System.Web.UI.Design.WebControls.ListControlDataBindingHandler, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
16 public partial class Beneficiaries : System.Web.UI.UserControl{
17
18 private ArrayList _Beneficiaries;
19
20 protected void Page_Load(object sender, EventArgs e) {
21
22 }
23
24 [DefaultValue((string)null), MergableProperty(false),
25 PersistenceMode(PersistenceMode.InnerDefaultProperty),
26 Editor("System.Web.UI.Design.WebControls.ListItemsCollectionEditor,System.Design, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
27 typeof(UITypeEditor))]
28 public virtual ArrayList Items {
29 get {
30 if (this._Beneficiaries == null) {
31 this._Beneficiaries = new ArrayList();
32 }
33 return _Beneficiaries;
34 }
35 }
36
37 protected override void CreateChildControls() {
38 if (this._Beneficiaries == null) {
39 this._Beneficiaries = new ArrayList();
40 }
41 foreach (object item in _Beneficiaries) {
42 container.Controls.Add((beneficiaryInput)item);
43 }
44 }
45
46 public void addBeneficiary() {
47 Control c = LoadControl("~/beneficiaryInput.ascx");
48
49 container.Controls.Add(c);
50 if (this._Beneficiaries == null) {
51 this._Beneficiaries = new ArrayList();
52 }
53 _Beneficiaries.Add(c);
54 }
55 }<%@ Control Language="C#" AutoEventWireup="true" CodeFile="beneficiaryInput.ascx.cs" Inherits="beneficiaryInput" %>Child Control Code:
<h3 runat="server" id="h3Title"></h3>
<label for="title">Title:</label> <asp:TextBox runat="server" ID="Title" CssClass="text" /> <span class="red">*</span><br />
<label for="forenames">Forename(s):</label> <asp:TextBox runat="server" ID="Forenames" CssClass="text" /> <span class="red">*</span><br />
<label for="surname">Surname:</label> <asp:TextBox runat="server" ID="Surname" CssClass="text" /> <span class="red">*</span><br /><br />
<label for="gender">Gender:</label>
<asp:RadioButton ID="female" GroupName="Gender" runat="server" /> Female
<asp:RadioButton ID="male" GroupName="Gender" runat="server" /> Male
<br /><br />
<label for="receive">To receive:</label> <asp:TextBox runat="server" ID="receive" CssClass="text" /> <a class="boxhelppopup-0"><img src="images/help-icon.gif" width="19" height="19" alt="" /></a><br /><br /><br />
<label for="postCode">Post Code:</label> <input type="text" id="txtPostcodeLookup" class="text" maxlength="12" runat="server" /> <span class="red">*</span> <a href="#this" title="Find My Address"><img runat="server" id="addressFinder" src="images/buttons/find-my-address.gif" width="136" height="29" alt="Find My Address" style="vertical-align:middle;" /></a><br /><br />
<div runat="server" id="divAddressList" style="display:none;">
<label for="postCode">Select Address:</label>
<div id="divInnerAddressList"></div>
</div>
<div runat="server" id="divAddressDetails" style="display:none;">
<label for="houseNumber">House No/Name:</label> <asp:TextBox runat="server" ID="houseNumber" CssClass="text" /> <span class="red">*</span><br />
<label for="postCode">Post Code:</label> <asp:TextBox runat="server" ID="postCode" CssClass="text" /> <span class="red">*</span><br /><br />
<label for="address">Address:</label> <asp:TextBox runat="server" ID="address" CssClass="text" /><br />
<label for="address2">Address2:</label> <asp:TextBox runat="server" ID="address2" CssClass="text" /><br />
<label for="town">Town:</label> <asp:TextBox runat="server" ID="town" CssClass="text" /> <span class="red">*</span><br />
<label for="country">Country:</label> <asp:TextBox runat="server" ID="country" CssClass="text" /><br /><br /><br />
</div>
<asp:CheckBox runat="server" ID="isActive" OnCheckedChanged="isActive_OnCheckChange" Visible="false" />1 using System;
2 using System.Collections.Generic;
3 using System.Web;
4 using System.Web.UI;
5 using System.Web.UI.WebControls;
6
7 public partial class beneficiaryInput : System.Web.UI.UserControl {
8
9 protected void Page_Init() {
10 //addressFinder.Attributes.Add("onclick", "addressFinder('" + this.ClientID + "')");
11 }
12
13 protected void Page_Load(object sender, EventArgs e) {
14
15 }
16
17 protected void isActive_OnCheckChange(object sender, EventArgs e) {
18 this.Visible = ((CheckBox)sender).Checked;
19 }
20
21 public bool active {
22 get {
23 return isActive.Checked;
24 }
25 set {
26 isActive.Checked = value;
27 this.Visible = value;
28 }
29 }
30
31 public string headerText {
32 get {
33 return h3Title.InnerText;
34 }
35 set {
36 h3Title.InnerText = value;
37 }
38 }
39
40 public string beneficiaryTitle {
41 get {
42 return Title.Text;
43 }
44 set {
45 Title.Text = value;
46 }
47 }
48
49 public string beneficiaryForenames {
50 get {
51 return Forenames.Text;
52 }
53 set {
54 Forenames.Text = value;
55 }
56 }
57
58 public string beneficiarySurname {
59 get {
60 return Surname.Text;
61 }
62 set {
63 Surname.Text = value;
64 }
65 }
66
67 public string beneficiaryGender {
68 get {
69 if (male.Checked) {
70 return "M";
71 }
72 if (female.Checked) {
73 return "F";
74 }
75 return "";
76 }
77 set {
78 if (value.ToLower() == "m") {
79 female.Checked = false;
80 male.Checked=true;
81 }
82 if (value.ToLower() == "f") {
83 male.Checked = false;
84 female.Checked=true;
85 }
86 }
87 }
88
89 public string beneficiaryPercentage {
90 get {
91 return receive.Text;
92 }
93 set {
94 receive.Text = value;
95 }
96 }
97
98 public string beneficiaryAddress1{
99 get{
100 return address.Text;
101 }
102 set{
103 address.Text=value;
104 }
105 }
106
107 public string beneficiaryAddress2{
108 get{
109 return address2.Text;
110 }
111 set{
112 address2.Text = value;
113 }
114 }
115
116 public string beneficiaryTown{
117 get{
118 return town.Text;
119 }
120 set{
121 town.Text = value;
122 }
123 }
124
125 public string beneficiaryCountry{
126 get{
127 return country.Text;
128 }
129 set{
130 country.Text = value;
131 }
132 }
133
134 public string beneficiaryPostcode{
135 get{
136 return postCode.Text;
137 }
138 set{
139 postCode.Text = value;
140 }
141 }
142 }
143
![]() |
0 |
![]() |
dynamically added controls need to be recreated and readded to the page on each and every postback - by page_load at the latest.
give this a read: http://forums.asp.net/t/1186195.aspx
Mike Banavige
~~~~~~~~~~~~
Need a site code sample in a different language? Try converting it with: http://converter.telerik.com/
![]() |
0 |
![]() |
Cheers for that, however, shouldn't the contents of the ArrayList in the parent User Control persist the items added across postbacks?
That way I can loop through ArrayList on Page_Load on the parent User Control, adding the Child User Controls.
However, if I do a testControl.addBeneficiary(), then on the next postback output testControl.Items.Count it returns a 0.
Any suggestions as to why the ArrayList isn't persisting?
Thanks in advance
![]() |
0 |
![]() |
No page variables will survive across a postback unless you take steps to persist them. on a postback, a brand new page instance is created and it has no knowledge of what wah done in the previous page instance. this is the nature of the web - it is stateless. If you want values to survive postbacks, you need to persist those values somewhere such as ViewState, Session, Cookies, Database.
http://wiki.asp.net/page.aspx/30/state-management/
Mike Banavige
~~~~~~~~~~~~
Need a site code sample in a different language? Try converting it with: http://converter.telerik.com/
![]() |
0 |
![]() |
I appreciate that, however surely the whole point of the viewstate is to provide a framework that does that for you?
With dynamically loaded controls I would expect to have to add their state to the viewstate via code, but with those those added at design time I would expect to work in the same way as another asp tag.
With a textbox, if I set it's text attribute to 'fred' via code at step 1, at step 3 it is still 'fred' - imo an attribute set on a user control should operate in the same fashion. This isn't what's happening in this case.
After all, an integer is an integer is an integer, regardless of whether it's in an aspx form or an ascx control.
If I have to do it purely in code, then so be it, it just seems somewhat inelegant when it's handled so seamlessly with the pre-existing tags.
Thanks anyway.
![]() |
0 |
![]() |
ManchesterCodeMonkey:
I appreciate that, however surely the whole point of the viewstate is to provide a framework that does that for you?no. if every page level variable that you used was automatically stuffed into viewstate, then your pages (rendered to the client) would be painfully large. Also keep in mind that not everything can be put in viewstate unless it is marked as serializable. Viewstate is something that you need to opt into. It is not automatic.
ManchesterCodeMonkey:
With a textbox, if I set it's text attribute to 'fred' via code at step 1, at step 3 it is still 'fred'The textbox retains its Text propertys value due to the forms post data - not from viewstate. Other properties of that control will persist across postbacks as the control developer placed those values in ViewState explicitly. i.e they opted in to viewstate for certain properties.
Your arraylist is a variable that you have created in your class and the framework makes no assumptions about how you intend to handle it. As a general rule, you do not create control instances and place them in viewstate. Instead you place information in viewstate that allows you to recreate the dynamic controls on postback. Remember, any data you place in viewstate is sent to the client browser in a hidden form field. overusing viewstate can make you page size dramatically large and make you page feel unresponsive.
Mike Banavige
~~~~~~~~~~~~
Need a site code sample in a different language? Try converting it with: http://converter.telerik.com/
![]() |
0 |
![]() |