Click here to Skip to main content
11,427,946 members (56,832 online)
Rate this: bad
good
Please Sign up or sign in to vote.
See more: ASP.NET custom-controls , +
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 20-May-11 0:11am
EnkelIk369
Edited 20-May-11 0:13am
v2

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



Advertise | Privacy | Mobile
Web03 | 2.8.150428.2 | Last Updated 20 May 2011
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100