C
Christophe Peillet
I have been developing a set of custom controls that include several
dynamically generated controls inside them (for example, 'SupportTextBox'
include a textbox, a label, and a validation icon used if the field is
mandatory). These controls also support AJAX callbacks. Everything works
fine when used in 'Callback' mode, but when the controls are used as normal
form controls (non-Callback, meaning they are rendered as standard TextBoxes,
CheckBoxes, etc.), the postback destroys any changes made to the dynamically
generated controls.
For example, if the 'TextBoxText' properties initial value is set to
String.Empty, and I change this value to 'Test' on the form, and raise a
postback via a button, the value is always String.Empty when the page reloads.
I know there are some specific issues with PostBack and dynamic controls
(I've spent a week trying to understand how to fix this issue, but only run
in circles at this point).
If someone can show me (clearly) how I can maintain the state of the dynamic
controls after a postback, it would be enormously appreciated. I've read
perhaps 30 articles dealing with this in some manner or another, but have
never found something clear that address my problem. (I.e., I'm not asking
because I'm lazy and haven't tried to solve this myself).
A sample class is included below to help see where the problem may be. For
reference sake, this control (SupportTextBox) inherits from several others
objects in the hierarchy, but the relevant logic should all be contained here.
-----
[SupportTextBox.cs]
-----
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using Telerik.WebControls;
namespace Epson.EEE.Web.UI.FormControls
{
/// <summary>
/// An AJAX enabled TextBox control, which automatically applies the
Epson style guide to its appearance.
/// </summary>
/// <seealso cref="T:SupportTextBoxDesigner"/>
/// <seealso cref="T:SupportTextBoxActionList"/>
[Designer(typeof(SupportTextBoxDesigner))]
[DefaultProperty("Text")]
[DefaultEvent("TextChanged")]
[ToolboxData("<{0}:SupportTextBox runat=server></{0}:SupportTextBox>")]
public class SupportTextBox : SupportFormLabelledControl
{
#region Internal Fields
// Any third-party or external controls that you wish to add to the
this
// control, such as buttons, labels, etc., should be declared here.
// Declare any required controls/objects
private CallbackTextBox m_txt;
private CallbackLabel m_lbl;
private IconPopupControl m_icn;
#endregion
#region Event Handlers
// Declare any events that will be raised by this control.
/// <summary>
/// Fires when the textbox's text content is changed, and focus is
lost from the control. (Please note that this event only fires when <see
cref="P:SupportTextBox.CallbackEnabled"/> is set to True.)
/// </summary>
[Category("Action")]
[Description("Fires when the text is changed. (Please note that
this event only fires when CallbackEnabled is set to True.)")]
public event EventHandler TextChanged;
#endregion
#region Constructor
// Default values for properties should ONLY be defined in the the
// class constructor. If you set properties elsewhere, such as in the
// OnLoad event, you will make the control insensitive to external,
// tag-level settings.
/// <summary>
/// Initializes a new instance of the <see cref="SupportTextBox"/>
class.
/// </summary>
public SupportTextBox()
{
// Set default values
this.SetDefaultValues();
}
#endregion
#region Protected Methods (Page Events)
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Init"></see> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"></see> object
that contains the event data.</param>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Load"></see> event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"></see> object
that contains the event data.</param>
protected override void OnLoad(EventArgs e)
{
// This method captures the controls Load event (declared and
bound in the
// class constructor). RunTime rendering takes place in this
method (as
// opposed to DesignMode rendering, which takes place elsewhere).
// Call base Load method
base.OnLoad(e);
EnsureChildControls();
// Make sure we are not running in DesignMode
if (!(this.DesignMode))
{
this.SetRunTimeProperties();
}
}
/// <summary>
/// Called by the ASP.NET page framework to notify server controls
that use
/// composition-based implementation to create any child controls
they contain
/// in preparation for posting back or rendering.
/// </summary>
protected override void CreateChildControls()
{
// Clear the control collection
Controls.Clear();
// Any dependant controls used in this custom control must
// be added to the control 'hierarchy'. If they are not added
// to the control collection, they will not be visible to other
// controls on the page.
// Instantiate any dependant controls
m_txt = new CallbackTextBox();
m_lbl = new CallbackLabel();
m_icn = new IconPopupControl();
// Register any events associated with dependant controls
m_txt.TextChanged += new EventHandler(TextChangedEvent);
// Add them to the control collection
Controls.Add(m_txt);
Controls.Add(m_lbl);
Controls.Add(m_icn);
// Call base method
base.CreateChildControls();
}
/// <summary>
/// Renders the contents of the control to the specified writer.
This method is used primarily by control developers.
/// </summary>
/// <param name="output">A <see
cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output
stream to render HTML content on the client.</param>
protected override void RenderContents(HtmlTextWriter output)
{
EnsureChildControls();
// Render temporary values if running in DesignMode. This
allows users
// to see the control as it will appear in the RunTime
environment.
if (this.DesignMode)
{
SetDesignTimeProperties();
}
else
{
SetRunTimeProperties();
}
// Create temporary HtmlTextWriter placeholder
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
// Create table to hold results
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table);
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
// Render dependent controls
switch (this.LabelPosition)
{
case Position.Left:
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Top:
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Colspan,
"2");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Right:
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Bottom:
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
// Label
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Colspan,
"2");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
default:
Debug.Assert(false);
break;
}
// Close table tag
htmlWriter.RenderEndTag();
// If you wish to make any modifications to the raw Html code
// before it is send to the output stream (for example, ensuring
// that the code is XHtml compliant, etc.), you can make the
// modifications to the 'rawHtml' field below. This code will
// then be sent to the real Html output stream.
string rawHtml = stringBuilder.ToString();
output.Write(rawHtml);
}
/// <summary>
/// Raised when the user changes the content of the textbox. This
event only fires when <see cref="P:SupportTextBox.CallbackEnabled"/> is set
to True.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance
containing the event data.</param>
protected void TextChangedEvent(object sender, EventArgs e)
{
// ToDo: Is there a better way to do this (update properties
automatically)
this.TextboxText = ((CallbackTextBox)sender).Text;
// Make sure we are not running in DesignMode
if (!(this.DesignMode))
{
if (!(TextChanged == null))
{
this.TextChanged(sender, new EventArgs());
}
}
}
#endregion
#region Private Methods
/// <summary>
/// Sets the control's default values.
/// </summary>
private void SetDefaultValues()
{
// Set properties to default values
this.TextboxCssClass = SharedConstants.SupportForm_TextBoxStyle;
this.TextboxMaxLength = 0;
this.TextboxReadOnly = false;
this.TextboxText = string.Empty;
}
/// <summary>
/// Sets the properties of this control when executing in a design
time environment.
/// </summary>
private void SetDesignTimeProperties()
{
// Associate dependent control properties with this control's
properties
m_lbl.CssClass = this.LabelCssClass;
m_lbl.Text = this.LabelText == string.Empty ?
m_lbl.Text = "[LabelText]" :
m_lbl.Text = this.LabelText;
m_lbl.Visible = this.LabelVisible;
m_lbl.RadControlsDir = this.ScriptsPath;
m_lbl.CallbackEnabled = this.CallbackEnabled;
m_lbl.DisableAtCallback = this.DisableAtCallback;
m_lbl.Enabled = this.Enabled;
m_txt.MaxLength = this.TextboxMaxLength;
m_txt.ReadOnly = this.TextboxReadOnly;
m_txt.RadControlsDir = this.ScriptsPath;
m_txt.DisableAtCallback = this.DisableAtCallback;
m_txt.CallbackEnabled = this.CallbackEnabled;
m_txt.CssClass = this.TextboxCssClass;
m_txt.Enabled = this.Enabled;
m_icn.ImageUrl = this.WarningImageUrl;
m_icn.ImageAlign = this.ImageAlign;
m_icn.EmptyImageUrl = this.EmptyImageUrl;
m_icn.MessageStyle = this.MessageStyle;
m_icn.PopupText = this.PopupText;
m_icn.PopupTextResourceKey = this.PopupTextResourceKey;
m_icn.PopupTitle = this.PopupTitle;
m_icn.PopupTitleResourceKey = this.PopupTitleResourceKey;
m_icn.WarningIconVisible = this.WarningIconVisible;
m_icn.Enabled = this.Enabled;
m_icn.CssClass = this.WarningIconCssStyle;
}
/// <summary>
/// Sets the properties of this control when executing in a run time
environment.
/// </summary>
private void SetRunTimeProperties()
{
// Associate dependent control properties with this control's
properties
m_lbl.CssClass = this.LabelCssClass;
m_lbl.Text = this.LabelText;
m_lbl.Visible = this.LabelVisible;
m_lbl.RadControlsDir = this.ScriptsPath;
m_lbl.CallbackEnabled = this.CallbackEnabled;
m_lbl.DisableAtCallback = this.DisableAtCallback;
m_lbl.Enabled = this.Enabled;
m_txt.MaxLength = this.TextboxMaxLength;
m_txt.ReadOnly = this.TextboxReadOnly;
m_txt.RadControlsDir = this.ScriptsPath;
m_txt.DisableAtCallback = this.DisableAtCallback;
m_txt.CallbackEnabled = this.CallbackEnabled;
m_txt.CssClass = this.TextboxCssClass;
m_txt.Enabled = this.Enabled;
m_icn.ImageUrl = this.WarningImageUrl;
m_icn.ImageAlign = this.ImageAlign;
m_icn.EmptyImageUrl = this.EmptyImageUrl;
m_icn.MessageStyle = this.MessageStyle;
m_icn.PopupText = this.PopupText;
m_icn.PopupTextResourceKey = this.PopupTextResourceKey;
m_icn.PopupTitle = this.PopupTitle;
m_icn.PopupTitleResourceKey = this.PopupTitleResourceKey;
m_icn.WarningIconVisible = this.WarningIconVisible;
m_icn.Enabled = this.Enabled;
m_icn.CssClass = this.WarningIconCssStyle;
}
#endregion
#region Protected Properties
/// <summary>
/// Gets or sets the number of controls in the Control collection
/// (used to manage a counter stored in ViewState).
/// </summary>
/// <value>The number of controls in the Control collection.</value>
protected int NumberOfControls
{
get
{
int i = (int)ViewState["NumControls"];
return i;
}
set
{
ViewState["NumControls"] = value;
}
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the textbox CSS class.
/// </summary>
/// <value>The textbox CSS class.</value>
[Bindable(true)]
[Category("Textbox")]
[Description("The Css Class associated with the textbox.")]
[Localizable(false)]
public string TextboxCssClass
{
get
{
string s = (string)ViewState["TextboxCssClass"];
return s;
}
set
{
Debug.Assert(value != null, "Warning: TextboxCssClass
property is null!");
if (value != null)
{
ViewState["TextboxCssClass"] = value;
}
else
{
throw new NullReferenceException("TextboxCssClass can
not be assigned a null value.");
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the textbox is read only.
/// </summary>
/// <value><c>true</c> if read only; otherwise, <c>false</c>.</value>
[Bindable(true)]
[Category("Textbox")]
[DefaultValue(typeof(bool), "False")]
[Description("Whether the textbox contents can be modified by users
or not.")]
[Localizable(false)]
public bool TextboxReadOnly
{
get
{
bool b = (bool)ViewState["TextboxReadOnly"];
return b;
}
set
{
ViewState["TextboxReadOnly"] = value;
}
}
/// <summary>
/// Gets or sets the textbox text.
/// </summary>
/// <value>The textbox text.</value>
[Bindable(true)]
[Category("Textbox")]
[DefaultValue(typeof(string), "")]
[Description("The text that will be displayed in the textbox.")]
[Localizable(true)]
public string TextboxText
{
get
{
string s = (string)ViewState["TextboxText"];
return s;
}
set
{
Debug.Assert(value != null, "Warning: TextboxText property
is null!");
if (value != null)
{
ViewState["TextboxText"] = value;
this.EnsureChildControls();
}
else
{
throw new NullReferenceException("TextboxText can not be
assigned a null value.");
}
}
}
/// <summary>
/// Gets or sets the maximum length (in characters) of the text box
content.
/// </summary>
/// <value>The maximum length of the text box content.</value>
[Bindable(true)]
[Category("Textbox")]
[Description("The maximum number of characters that can be entered
in the textbox.")]
[Localizable(false)]
public int TextboxMaxLength
{
get
{
int i = (int)ViewState["TextboxMaxLength"];
return i;
}
set
{
ViewState["TextboxMaxLength"] = value;
}
}
#endregion
}
}
dynamically generated controls inside them (for example, 'SupportTextBox'
include a textbox, a label, and a validation icon used if the field is
mandatory). These controls also support AJAX callbacks. Everything works
fine when used in 'Callback' mode, but when the controls are used as normal
form controls (non-Callback, meaning they are rendered as standard TextBoxes,
CheckBoxes, etc.), the postback destroys any changes made to the dynamically
generated controls.
For example, if the 'TextBoxText' properties initial value is set to
String.Empty, and I change this value to 'Test' on the form, and raise a
postback via a button, the value is always String.Empty when the page reloads.
I know there are some specific issues with PostBack and dynamic controls
(I've spent a week trying to understand how to fix this issue, but only run
in circles at this point).
If someone can show me (clearly) how I can maintain the state of the dynamic
controls after a postback, it would be enormously appreciated. I've read
perhaps 30 articles dealing with this in some manner or another, but have
never found something clear that address my problem. (I.e., I'm not asking
because I'm lazy and haven't tried to solve this myself).
A sample class is included below to help see where the problem may be. For
reference sake, this control (SupportTextBox) inherits from several others
objects in the hierarchy, but the relevant logic should all be contained here.
-----
[SupportTextBox.cs]
-----
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using Telerik.WebControls;
namespace Epson.EEE.Web.UI.FormControls
{
/// <summary>
/// An AJAX enabled TextBox control, which automatically applies the
Epson style guide to its appearance.
/// </summary>
/// <seealso cref="T:SupportTextBoxDesigner"/>
/// <seealso cref="T:SupportTextBoxActionList"/>
[Designer(typeof(SupportTextBoxDesigner))]
[DefaultProperty("Text")]
[DefaultEvent("TextChanged")]
[ToolboxData("<{0}:SupportTextBox runat=server></{0}:SupportTextBox>")]
public class SupportTextBox : SupportFormLabelledControl
{
#region Internal Fields
// Any third-party or external controls that you wish to add to the
this
// control, such as buttons, labels, etc., should be declared here.
// Declare any required controls/objects
private CallbackTextBox m_txt;
private CallbackLabel m_lbl;
private IconPopupControl m_icn;
#endregion
#region Event Handlers
// Declare any events that will be raised by this control.
/// <summary>
/// Fires when the textbox's text content is changed, and focus is
lost from the control. (Please note that this event only fires when <see
cref="P:SupportTextBox.CallbackEnabled"/> is set to True.)
/// </summary>
[Category("Action")]
[Description("Fires when the text is changed. (Please note that
this event only fires when CallbackEnabled is set to True.)")]
public event EventHandler TextChanged;
#endregion
#region Constructor
// Default values for properties should ONLY be defined in the the
// class constructor. If you set properties elsewhere, such as in the
// OnLoad event, you will make the control insensitive to external,
// tag-level settings.
/// <summary>
/// Initializes a new instance of the <see cref="SupportTextBox"/>
class.
/// </summary>
public SupportTextBox()
{
// Set default values
this.SetDefaultValues();
}
#endregion
#region Protected Methods (Page Events)
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Init"></see> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"></see> object
that contains the event data.</param>
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
}
/// <summary>
/// Raises the <see cref="E:System.Web.UI.Control.Load"></see> event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"></see> object
that contains the event data.</param>
protected override void OnLoad(EventArgs e)
{
// This method captures the controls Load event (declared and
bound in the
// class constructor). RunTime rendering takes place in this
method (as
// opposed to DesignMode rendering, which takes place elsewhere).
// Call base Load method
base.OnLoad(e);
EnsureChildControls();
// Make sure we are not running in DesignMode
if (!(this.DesignMode))
{
this.SetRunTimeProperties();
}
}
/// <summary>
/// Called by the ASP.NET page framework to notify server controls
that use
/// composition-based implementation to create any child controls
they contain
/// in preparation for posting back or rendering.
/// </summary>
protected override void CreateChildControls()
{
// Clear the control collection
Controls.Clear();
// Any dependant controls used in this custom control must
// be added to the control 'hierarchy'. If they are not added
// to the control collection, they will not be visible to other
// controls on the page.
// Instantiate any dependant controls
m_txt = new CallbackTextBox();
m_lbl = new CallbackLabel();
m_icn = new IconPopupControl();
// Register any events associated with dependant controls
m_txt.TextChanged += new EventHandler(TextChangedEvent);
// Add them to the control collection
Controls.Add(m_txt);
Controls.Add(m_lbl);
Controls.Add(m_icn);
// Call base method
base.CreateChildControls();
}
/// <summary>
/// Renders the contents of the control to the specified writer.
This method is used primarily by control developers.
/// </summary>
/// <param name="output">A <see
cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output
stream to render HTML content on the client.</param>
protected override void RenderContents(HtmlTextWriter output)
{
EnsureChildControls();
// Render temporary values if running in DesignMode. This
allows users
// to see the control as it will appear in the RunTime
environment.
if (this.DesignMode)
{
SetDesignTimeProperties();
}
else
{
SetRunTimeProperties();
}
// Create temporary HtmlTextWriter placeholder
StringBuilder stringBuilder = new StringBuilder();
StringWriter stringWriter = new StringWriter(stringBuilder);
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
// Create table to hold results
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table);
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
// Render dependent controls
switch (this.LabelPosition)
{
case Position.Left:
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Top:
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Colspan,
"2");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Right:
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
// Label
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Style,
"width: " + this.LabelWidth.ToString() + ";");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
case Position.Bottom:
// Textbox
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_txt.RenderControl(htmlWriter);
// Render the popup icon control if required
if (this.Required)
{
m_icn.RenderControl(htmlWriter);
}
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
// Label
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
htmlWriter.AddAttribute(HtmlTextWriterAttribute.Colspan,
"2");
htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
m_lbl.RenderControl(htmlWriter);
htmlWriter.RenderEndTag();
htmlWriter.RenderEndTag();
break;
default:
Debug.Assert(false);
break;
}
// Close table tag
htmlWriter.RenderEndTag();
// If you wish to make any modifications to the raw Html code
// before it is send to the output stream (for example, ensuring
// that the code is XHtml compliant, etc.), you can make the
// modifications to the 'rawHtml' field below. This code will
// then be sent to the real Html output stream.
string rawHtml = stringBuilder.ToString();
output.Write(rawHtml);
}
/// <summary>
/// Raised when the user changes the content of the textbox. This
event only fires when <see cref="P:SupportTextBox.CallbackEnabled"/> is set
to True.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance
containing the event data.</param>
protected void TextChangedEvent(object sender, EventArgs e)
{
// ToDo: Is there a better way to do this (update properties
automatically)
this.TextboxText = ((CallbackTextBox)sender).Text;
// Make sure we are not running in DesignMode
if (!(this.DesignMode))
{
if (!(TextChanged == null))
{
this.TextChanged(sender, new EventArgs());
}
}
}
#endregion
#region Private Methods
/// <summary>
/// Sets the control's default values.
/// </summary>
private void SetDefaultValues()
{
// Set properties to default values
this.TextboxCssClass = SharedConstants.SupportForm_TextBoxStyle;
this.TextboxMaxLength = 0;
this.TextboxReadOnly = false;
this.TextboxText = string.Empty;
}
/// <summary>
/// Sets the properties of this control when executing in a design
time environment.
/// </summary>
private void SetDesignTimeProperties()
{
// Associate dependent control properties with this control's
properties
m_lbl.CssClass = this.LabelCssClass;
m_lbl.Text = this.LabelText == string.Empty ?
m_lbl.Text = "[LabelText]" :
m_lbl.Text = this.LabelText;
m_lbl.Visible = this.LabelVisible;
m_lbl.RadControlsDir = this.ScriptsPath;
m_lbl.CallbackEnabled = this.CallbackEnabled;
m_lbl.DisableAtCallback = this.DisableAtCallback;
m_lbl.Enabled = this.Enabled;
m_txt.MaxLength = this.TextboxMaxLength;
m_txt.ReadOnly = this.TextboxReadOnly;
m_txt.RadControlsDir = this.ScriptsPath;
m_txt.DisableAtCallback = this.DisableAtCallback;
m_txt.CallbackEnabled = this.CallbackEnabled;
m_txt.CssClass = this.TextboxCssClass;
m_txt.Enabled = this.Enabled;
m_icn.ImageUrl = this.WarningImageUrl;
m_icn.ImageAlign = this.ImageAlign;
m_icn.EmptyImageUrl = this.EmptyImageUrl;
m_icn.MessageStyle = this.MessageStyle;
m_icn.PopupText = this.PopupText;
m_icn.PopupTextResourceKey = this.PopupTextResourceKey;
m_icn.PopupTitle = this.PopupTitle;
m_icn.PopupTitleResourceKey = this.PopupTitleResourceKey;
m_icn.WarningIconVisible = this.WarningIconVisible;
m_icn.Enabled = this.Enabled;
m_icn.CssClass = this.WarningIconCssStyle;
}
/// <summary>
/// Sets the properties of this control when executing in a run time
environment.
/// </summary>
private void SetRunTimeProperties()
{
// Associate dependent control properties with this control's
properties
m_lbl.CssClass = this.LabelCssClass;
m_lbl.Text = this.LabelText;
m_lbl.Visible = this.LabelVisible;
m_lbl.RadControlsDir = this.ScriptsPath;
m_lbl.CallbackEnabled = this.CallbackEnabled;
m_lbl.DisableAtCallback = this.DisableAtCallback;
m_lbl.Enabled = this.Enabled;
m_txt.MaxLength = this.TextboxMaxLength;
m_txt.ReadOnly = this.TextboxReadOnly;
m_txt.RadControlsDir = this.ScriptsPath;
m_txt.DisableAtCallback = this.DisableAtCallback;
m_txt.CallbackEnabled = this.CallbackEnabled;
m_txt.CssClass = this.TextboxCssClass;
m_txt.Enabled = this.Enabled;
m_icn.ImageUrl = this.WarningImageUrl;
m_icn.ImageAlign = this.ImageAlign;
m_icn.EmptyImageUrl = this.EmptyImageUrl;
m_icn.MessageStyle = this.MessageStyle;
m_icn.PopupText = this.PopupText;
m_icn.PopupTextResourceKey = this.PopupTextResourceKey;
m_icn.PopupTitle = this.PopupTitle;
m_icn.PopupTitleResourceKey = this.PopupTitleResourceKey;
m_icn.WarningIconVisible = this.WarningIconVisible;
m_icn.Enabled = this.Enabled;
m_icn.CssClass = this.WarningIconCssStyle;
}
#endregion
#region Protected Properties
/// <summary>
/// Gets or sets the number of controls in the Control collection
/// (used to manage a counter stored in ViewState).
/// </summary>
/// <value>The number of controls in the Control collection.</value>
protected int NumberOfControls
{
get
{
int i = (int)ViewState["NumControls"];
return i;
}
set
{
ViewState["NumControls"] = value;
}
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the textbox CSS class.
/// </summary>
/// <value>The textbox CSS class.</value>
[Bindable(true)]
[Category("Textbox")]
[Description("The Css Class associated with the textbox.")]
[Localizable(false)]
public string TextboxCssClass
{
get
{
string s = (string)ViewState["TextboxCssClass"];
return s;
}
set
{
Debug.Assert(value != null, "Warning: TextboxCssClass
property is null!");
if (value != null)
{
ViewState["TextboxCssClass"] = value;
}
else
{
throw new NullReferenceException("TextboxCssClass can
not be assigned a null value.");
}
}
}
/// <summary>
/// Gets or sets a value indicating whether the textbox is read only.
/// </summary>
/// <value><c>true</c> if read only; otherwise, <c>false</c>.</value>
[Bindable(true)]
[Category("Textbox")]
[DefaultValue(typeof(bool), "False")]
[Description("Whether the textbox contents can be modified by users
or not.")]
[Localizable(false)]
public bool TextboxReadOnly
{
get
{
bool b = (bool)ViewState["TextboxReadOnly"];
return b;
}
set
{
ViewState["TextboxReadOnly"] = value;
}
}
/// <summary>
/// Gets or sets the textbox text.
/// </summary>
/// <value>The textbox text.</value>
[Bindable(true)]
[Category("Textbox")]
[DefaultValue(typeof(string), "")]
[Description("The text that will be displayed in the textbox.")]
[Localizable(true)]
public string TextboxText
{
get
{
string s = (string)ViewState["TextboxText"];
return s;
}
set
{
Debug.Assert(value != null, "Warning: TextboxText property
is null!");
if (value != null)
{
ViewState["TextboxText"] = value;
this.EnsureChildControls();
}
else
{
throw new NullReferenceException("TextboxText can not be
assigned a null value.");
}
}
}
/// <summary>
/// Gets or sets the maximum length (in characters) of the text box
content.
/// </summary>
/// <value>The maximum length of the text box content.</value>
[Bindable(true)]
[Category("Textbox")]
[Description("The maximum number of characters that can be entered
in the textbox.")]
[Localizable(false)]
public int TextboxMaxLength
{
get
{
int i = (int)ViewState["TextboxMaxLength"];
return i;
}
set
{
ViewState["TextboxMaxLength"] = value;
}
}
#endregion
}
}