http://weblogs.asp.net/jcogley/archive/2005/09/21/425762.aspx

public static void ReadOnlyControls(Control control)
{
	if (control is WebControl)
	{
		WebControl webControl = (WebControl) control;
		string typeName = webControl.GetType().Name;
		switch (typeName)
		{
			case "LinkButton":
			case "DataGridLinkButton":
			case "TextBox":
			case "RadioButton":
			case "CheckBox":
				SwapControl(webControl, GetPropertyValue(webControl, "Text"));
				break;
			case "Button":
				webControl.Visible = false;
				break;
			case "RadioButtonList":
			case "DropDownList":
				ListControl list = (ListControl) webControl;
				string text = "";
				if (list.SelectedItem != null)
				{
					text = list.SelectedItem.Text;
				}
				SwapControl(webControl, text);
				break;
			case "ImageButton":
				webControl.Visible = false;
				break;
			case "DataGrid":
				DataGrid grid = (DataGrid) webControl;
				foreach (DataGridItem item in grid.Items)
				{
					foreach (Control itemControl in item.Controls)
					{
						ReadOnlyControls(itemControl);
					}
				}
				break;
			default:
				//Response.Write(webControl.GetType().FullName + "<BR>");
				break;
		}
	}
	for (int n = 0; n < control.Controls.Count; n++)
	{
		Control childControl = control.Controls[n];
		ReadOnlyControls(childControl);
	}
}

public static void SwapControl(Control oldControl, Control newControl) 
{
	Control parent = oldControl.Parent;
	int index = parent.Controls.IndexOf(oldControl);
	parent.Controls.RemoveAt(index);
	parent.Controls.AddAt(index, newControl);
}

public static void SwapControl(Control oldControl, string text) 
{
	SwapControl(oldControl, new LiteralControl(text));
}

public static string GetPropertyValue(Control control, string propertyName)
{
	Type type = control.GetType();
	object o = type.InvokeMember(propertyName, BindingFlags.Instance | 
           BindingFlags.GetProperty | BindingFlags.Public, null, control, null);
	return Convert.ToString(o);
}