Click here to Skip to main content
15,884,472 members
Please Sign up or sign in to vote.
4.00/5 (3 votes)
See more: , +
Hi all,

We just switched target framework in our ASP.NET web application from 3.5 to 4.0. We ran into the following problem:

We have a couple of custom controls that worked fine in 3.5 but now with 4.0 they are not persisted in ViewState, one of them is basically a wrapper for other controls that inherits the Label class and the aspx-code looks like this:
<fsc:FormLabel ID="l_purchaserNo" runat="server" CssClass="label" Text="Purchaser">
    <asp:TextBox ID="tb_purchaserNo" runat="server" CssClass="textBox" MaxLength="50" />
</fsc:FormLabel>
and the resulting html is:
<span id="l_purchaserNo" class="label">
    <label class="header" for="tb_purchaserNo">Purchaser</label>
    <span class="valueContainer">
        <input name="tb_purchaserNo" type="text" id="tb_purchaserNo" class="textBox" />
    </span>
</span>
So the control basically just adds a few span-tags and a label that is connected to the textbox.
After postback the html-code in 4.0 was:
<span id="l_purchaserNo" class="label"></span>

i.e. Everything within the outer wrapper was gone and anything entered in the textbox could not be retreived from code behind.
Below you find the code for our FormLabel class.
We found that by setting ViewStateMode=Disabled on our custom control fsc:FormLabel and ViewStateMode=Enabled on the asp:TextBox the inner controls where persisted to ViewState but at the same time we lost ViewState on the wrapper and since we translate the text on the wrapper label we need viewstate for this as well (actually we tried every combination and setting ViewStateMode=Enabled on fsc:FormLabel did not help, regardless of how we set the ViewStateMode on the page). EnableViewState is true on all levels.
Could someone tell us how to get ViewState to work as before in 3.5, on ALL controls - wrapper as well as wrapped controls?
Thanks
Christian, Zeljko, Jonas

using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace FormLabel
{
	public class FormLabel : Label
	{
		private bool HasChildren
		{
			get
			{
				return Controls.Count > 0;
			}
		}
		public override string Text
		{
			get
			{
				if (!HasChildren)
				{
					return base.Text;
				}
				var text = ViewState[ID + "Text"] as String;
				if (text != null)
				{
					((LiteralControl)Controls[0]).Text = text;
				}
				return ((LiteralControl)Controls[0]).Text;
			}
			set
			{
				if (!HasChildren)
				{
					base.Text = value;
					return;
				}
				((LiteralControl)Controls[0]).Text = value;
			}
		}
		public void SetText(string text)
		{
			((LiteralControl)Controls[0]).Text = text;
			ViewState[ID + "Text"] = text;
		}

		public bool IndicateRequired
		{
			get
			{
				object state = ViewState[String.Format("{0}_IR", ID)];
				return state != null && (bool)state;
			}
			set
			{
				ViewState[String.Format("{0}_IR", ID)] = value;
			}
		}
		protected override void OnLoad(EventArgs e)
		{			
			ViewState[ID + "Text"] = Text;
			base.OnLoad(e);
		}
		protected override void Render(HtmlTextWriter writer)
		{
			if (HasChildren)
			{
				List<Control> controls = Controls.GetControls();
				List<BaseValidator> validators = Controls.GetValidators();
				WriteLabelControl(writer);
				WriteRequiredIndicator(writer);
				WriteControlHeader(writer, validators, this.GetFirstControl());
				WriteInnerControls(writer, controls);
				WriteLabelEndControl(writer);
				return;
			}
			base.Render(writer);
		}
		private void WriteLabelControl(HtmlTextWriter writer)
		{
			writer.WriteBeginTag("span");
			writer.WriteAttribute("id", ClientID);
			writer.WriteAttribute("class", CssClass);
			foreach (string attributeKey in Attributes.Keys)
			{
				writer.WriteAttribute(attributeKey, Attributes[attributeKey]);
			}
			writer.Write(HtmlTextWriter.TagRightChar);
		}
		private void WriteRequiredIndicator(HtmlTextWriter writer)
		{
			if (IndicateRequired)
			{
				writer.WriteBeginTag("span");
				writer.WriteAttribute("class", "requiredIndicator");
				writer.Write(HtmlTextWriter.TagRightChar);
				writer.WriteEndTag("span");
			}
		}
		private void WriteControlHeader(HtmlTextWriter writer, IEnumerable<BaseValidator> validators, Control userControl)
		{
			writer.WriteBeginTag("label");
			writer.WriteAttribute("class", "header");
			if (userControl != null)
			{
				writer.WriteAttribute("for", userControl.ClientID);
			}
			writer.Write(HtmlTextWriter.TagRightChar);
			writer.Write(Text);
			foreach (BaseValidator validator in validators)
			{
				validator.CssClass = "Error";
				validator.RenderControl(writer);
			}
			writer.WriteEndTag("label");
		}
		private static void WriteInnerControls(HtmlTextWriter writer, IList<Control> controls)
		{
			writer.WriteBeginTag("span");
			writer.WriteAttribute("class", "valueContainer");
			writer.Write(HtmlTextWriter.TagRightChar);
			for (int i = 1; i < controls.Count; i++)
			{
				controls[i].RenderControl(writer);
			}
			writer.WriteEndTag("span");
		}
		private static void WriteLabelEndControl(HtmlTextWriter writer)
		{
			writer.WriteEndTag("span");
		}
	}
	#region Nested type: Extensions
	public static class Extensions
	{
		public static List<BaseValidator> GetValidators(this ControlCollection controls)
		{
			var validators = new List<BaseValidator>();
			foreach (Control c in controls)
			{
				if (c is BaseValidator)
				{
					validators.Add(c as BaseValidator);
				}
				
			}
			return validators;
		}
		public static List<Control> GetControls(this ControlCollection controls)
		{
			var listcontrols = new List<Control>();
			foreach (Control c in controls)
			{
				if (!(c is BaseValidator))
				{
					listcontrols.Add(c as Control);
				}
			}
			return listcontrols;
		}
		public static Control GetFirstControl(this Control container)
		{
			return (new InputControlFinder().FindFirstInputControl(container));
		}
		private class InputControlFinder
		{
			public Control FindFirstInputControl(Control control)
			{
				Control input = null;
				foreach (Control child in control.Controls)
				{
					if (child is TextBox || child is DropDownList || child is CheckBox)
					{
						input = child;
					}
					else
					{
						input = FindFirstInputControl(child);
					}
					if (input != null)
					{
						return input;
					}
				}
				return input;
			}
		}
	}
	#endregion
}
Posted
Updated 19-May-11 23:13pm
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900