Changed property values not reflected in DesignMode

Discussion in 'ASP .Net Web Controls' started by Christophe Peillet, Jan 9, 2006.

  1. I am in the process of developing several custom controls that have
    validation and Ajax/Callback support built into them, and have finished most
    of the work, but have a stubborn problem when running in DesignMode.

    When I try to modify the value of certain properties, the Html code is
    modified with the new property value (for example '... CheckboxText="MyText"
    .....'), but the visual display is never updated, and the property explorer
    window also doesn't reflect the new value. It behaves as if the property is
    read only, and allow no apparent change, even if it is changing the values
    beneath the surface, and the changes are visible at RunTime.

    I suspect the problem is that I have not properly understand the page model
    properly, and am putting something in the wrong place. (This is my first
    Custom Control that is more than something simplistic.) If someone can take
    a look specifically at the methods SetDesignTimeProperties() and
    SetRunTimeProperties(), I may be running this in the wrong place, but am not
    sure where else to run them, etc. I will also include the code for the
    designer in the next post (due to size restrictions). The Custom control is
    as follows:

    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.Drawing;
    using System.Diagnostics;
    using Telerik.WebControls;

    namespace CompanyName.EEE.Web.UI.FormControls
    {
    /// <summary>
    /// An AJAX enabled CheckBox control, which automatically applies the
    CompanyName style guide to its appearance.
    /// </summary>
    /// <seealso cref="T:SupportCheckBoxDesigner"/>
    /// <seealso cref="T:SupportCheckBoxActionList"/>
    [Designer(typeof(SupportCheckBoxDesigner))]
    [DefaultProperty("Text")]
    [DefaultEvent("OnCheckedChanged")]
    [ToolboxData("<{0}:SupportCheckBox
    runat=\"server\"></{0}:SupportCheckBox>")]
    [ParseChildren(true)]
    [PersistChildren(false)]
    [ControlValueProperty("CheckboxChecked")]
    public class SupportCheckBox : SupportFormLabelledControl,
    INamingContainer
    {
    #region Private 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 CallbackLabel m_lbl;
    private CallbackCheckBox m_chk;
    private IconPopupControl m_icn;

    #endregion

    #region Event Handlers

    // Declare any events that will be raised by this control.
    /// <summary>
    /// Occurs when the value of the Checked property changes. (This
    event only fires when <see cref="P:SupportCheckBox.CallbackEnabled"/> is set
    to True.)
    /// </summary>
    [Category("Action")]
    [Description("Occurs when the value of the Checked property changes.
    (Please note that this event only fires when CallbackEnabled is set to
    True.)")]
    public event EventHandler CheckedChanged;

    #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="SupportCheckBox"/>
    class.
    /// </summary>
    public SupportCheckBox()
    {
    // Set control 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))
    {
    // Associate dependent control properties with this
    control's properties
    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 dependent objects
    m_lbl = new CallbackLabel();
    m_chk = new CallbackCheckBox();
    m_icn = new IconPopupControl();

    // Register any event associated with dependant objects
    m_chk.CheckedChanged += new
    EventHandler(this.RaiseCheckedChanged);

    // Add them to the control collection
    Controls.Add(m_lbl);
    Controls.Add(m_chk);
    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)
    {
    this.SetDesignTimeProperties();
    }

    // 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();
    // Checkbox
    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
    m_chk.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();
    // Checkbox
    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Tr);
    htmlWriter.AddAttribute(HtmlTextWriterAttribute.Colspan,
    "2");
    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
    m_chk.RenderControl(htmlWriter);
    // Render the popup icon control if required
    if (this.Required)
    {
    m_icn.RenderControl(htmlWriter);
    }
    htmlWriter.RenderEndTag();
    htmlWriter.RenderEndTag();
    break;
    case Position.Right:
    // Checkbox
    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
    m_chk.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:
    // Checkbox
    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Td);
    m_chk.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>
    /// Fires when the value of the Checked property changes. This
    event only fires when <see cref="P:SupportCheckBox.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 virtual void RaiseCheckedChanged(object sender, EventArgs e)
    {
    // ToDo: Is there a better way to do this (update properties
    automatically)
    this.CheckboxChecked = ((CallbackCheckBox)sender).Checked;

    // Ensure that the event has a subscriber. If not, don't fire it.
    if (CheckedChanged != null)
    {
    // Raise the CheckedChanged event
    CheckedChanged(this, e);
    }
    }

    #endregion

    #region Private Methods

    /// <summary>
    /// Sets the control's default values.
    /// </summary>
    private void SetDefaultValues()
    {
    // Set properties to default values
    this.CheckboxChecked = false;
    this.CheckboxCssClass = SharedConstants.SupportForm_CheckBoxStyle;
    this.CheckboxEnabled = true;
    this.CheckboxText = string.Empty;
    this.CheckboxTextResourceKey = string.Empty;
    this.CheckboxVisible = true;
    }

    /// <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_chk.RadControlsDir = this.ScriptsPath;
    m_chk.CallbackEnabled = this.CallbackEnabled;
    m_chk.DisableAtCallback = this.DisableAtCallback;
    m_chk.Enabled = this.CheckboxEnabled;
    m_chk.CssClass = this.CheckboxCssClass;
    m_chk.Text = this.CheckboxText == string.Empty ?
    m_chk.Text = "[CheckboxText]" :
    m_chk.Text = this.CheckboxText;
    m_chk.Visible = this.CheckboxVisible;
    m_chk.Checked = this.CheckboxChecked;
    m_chk.AutoPostBack = this.AutoPostback;
    m_chk.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.CallbackEnabled = this.CallbackEnabled;
    m_icn.DisableAtCallback = this.DisableAtCallback;
    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()
    {
    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_chk.RadControlsDir = this.ScriptsPath;
    m_chk.CallbackEnabled = this.CallbackEnabled;
    m_chk.DisableAtCallback = this.DisableAtCallback;
    m_chk.Enabled = this.CheckboxEnabled;
    m_chk.CssClass = this.CheckboxCssClass;
    m_chk.Text = this.CheckboxText;
    m_chk.Visible = this.CheckboxVisible;
    m_chk.Checked = this.CheckboxChecked;
    m_chk.AutoPostBack = this.AutoPostback;
    m_chk.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.CallbackEnabled = this.CallbackEnabled;
    m_icn.DisableAtCallback = this.DisableAtCallback;
    m_icn.Enabled = this.Enabled;
    m_icn.CssClass = this.WarningIconCssStyle;
    }

    #endregion

    #region Public Properties

    /// <summary>
    /// Gets or sets the checkbox CSS class.
    /// </summary>
    /// <value>The checkbox CSS class.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(string), "")]
    [Description("CSS Class name applied to this control.")]
    [Localizable(false)]
    public string CheckboxCssClass
    {
    get
    {
    EnsureChildControls();
    return (m_chk.CssClass == null) ?
    string.Empty :
    m_chk.CssClass;
    }
    set
    {
    Debug.Assert(value != null, "Warning: CheckboxCssClass
    property is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_chk.CssClass = value;
    }
    else
    {
    throw new NullReferenceException("CheckboxCssClass can
    not be assigned a null value.");
    }
    }
    }

    /// <summary>
    /// Gets or sets the checkbox text.
    /// </summary>
    /// <value>The checkbox text.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(string), "")]
    [Description("The text that will be displayed with the checkbox.")]
    [Localizable(true)]
    [NotifyParentProperty(true)]
    [Browsable(true)]
    [RefreshProperties(RefreshProperties.All)]
    public string CheckboxText
    {
    get
    {
    EnsureChildControls();
    return (m_chk.Text == null) ?
    string.Empty :
    m_chk.Text;
    }
    set
    {
    Debug.Assert(value != null, "Warning: CheckboxText property
    is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_chk.Text = value;
    }
    else
    {
    throw new NullReferenceException("CheckboxText can not
    be assigned a null value.");
    }
    }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the checkbox is enabled.
    /// </summary>
    /// <value><c>true</c> if checkbox enabled; otherwise,
    <c>false</c>.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(bool), "True")]
    [Description("Whether or not the Checkbox is enabled.")]
    [Localizable(false)]
    public bool CheckboxEnabled
    {
    get
    {
    EnsureChildControls();
    return m_chk.Enabled;
    }
    set
    {
    EnsureChildControls();
    m_chk.Enabled = value;
    }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the checkbox is checked.
    /// </summary>
    /// <value><c>true</c> if checkbox checked; otherwise,
    <c>false</c>.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(bool), "False")]
    [Description("Whether or not the Checkbox is selected (checked) or
    not.")]
    [Localizable(false)]
    public bool CheckboxChecked
    {
    get
    {
    EnsureChildControls();
    return m_chk.Checked;
    }
    set
    {
    EnsureChildControls();
    m_chk.Checked = value;
    }
    }

    /// <summary>
    /// Gets or sets the checkbox text resource key.
    /// </summary>
    /// <value>The checkbox text resource key.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(string), "")]
    [Description("The resource key used when localising the Checkboxes
    text.")]
    [Localizable(false)]
    public string CheckboxTextResourceKey
    {
    get
    {
    string s = (string)ViewState["CheckboxTextResourceKey"];
    return (s == null) ? String.Empty : s;
    }
    set
    {
    Debug.Assert(value != null, "Warning:
    CheckboxTextResourceKey property is null!");
    if (value != null)
    {
    ViewState["CheckboxTextResourceKey"] = value;
    }
    else
    {
    throw new
    NullReferenceException("CheckboxTextResourceKey can not be assigned a null
    value.");
    }
    }
    }

    /// <summary>
    /// Gets or sets a value indicating whether the checkbox is visible
    or not.
    /// </summary>
    /// <value><c>true</c> if checkbox visible; otherwise,
    <c>false</c>.</value>
    [Bindable(true)]
    [Category("Checkbox")]
    [DefaultValue(typeof(bool), "True")]
    [Description("Whether or not the checkbox is visible.")]
    [Localizable(false)]
    public bool CheckboxVisible
    {
    get
    {
    EnsureChildControls();
    return m_chk.Visible;
    }
    set
    {
    EnsureChildControls();
    m_chk.Visible = value;
    }
    }

    #endregion
    }
    }
    Christophe Peillet, Jan 9, 2006
    #1
    1. Advertising

  2. Designer Code for this control

    Here is the Designer code for this control:

    using System;
    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 System.Drawing.Design;
    using Telerik.WebControls;

    namespace CompanyName.EEE.Web.UI.FormControls
    {

    #region Support CheckBox Designer

    // This designer class manages the control's Smart Tags, including any
    // properties and actions exposed within then. This particular class
    // serves as more of a 'manager', since most of the actual work takes
    // place in the class below that inherits from DesignerActionList.

    /// <summary>
    /// The designer used by <see cref="T:SupportCheckBox"></see> to add
    DesignMode functionality
    /// (such as SmartTags) to the Visual Studio 2005 IDE.
    /// </summary>
    /// <seealso cref="T:SupportTextBoxActionList"/>
    public class SupportCheckBoxDesigner : CompositeControlDesigner
    {
    #region Private Fields

    private DesignerActionListCollection lists;

    #endregion

    #region Public Methods (Overrides)

    /// <summary>
    /// Gets the action list collection for the control designer.
    /// </summary>
    /// <value></value>
    /// <returns>A <see
    cref="T:System.ComponentModel.Design.DesignerActionListCollection"></see>
    that contains the <see
    cref="T:System.ComponentModel.Design.DesignerActionList"></see> items for the
    control designer.</returns>
    public override DesignerActionListCollection ActionLists
    {
    get
    {
    if (lists == null)
    {
    lists = new DesignerActionListCollection();
    lists.Add(new SupportCheckBoxActionList(this.Component));
    }
    return lists;
    }
    }

    #endregion
    }

    #endregion

    #region Support CheckBox Action List

    // The inherited DesignerActionList class is designed to associate one
    or more
    // designer action items with a single component. Most of the actual
    DesignMode
    // and Smart Tag work takes place here.

    /// <summary>
    /// Associates one or more action items with the <see
    cref="T:SupportCheckBox"></see> Designer.
    /// </summary>
    /// <seealso cref="T:SupportCheckBoxDesigner"/>
    public class SupportCheckBoxActionList : DesignerActionList
    {
    #region Private Fields

    private SupportCheckBox m_checkBox;
    private DesignerActionUIService designerActionSvc = null;

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see
    cref="SupportCheckBoxActionList"/> class.
    /// </summary>
    /// <param name="component">A component related to the <see
    cref="T:System.ComponentModel.Design.DesignerActionList"></see>.</param>
    public SupportCheckBoxActionList(IComponent component)
    : base(component)
    {
    this.m_checkBox = (SupportCheckBox)component;
    this.designerActionSvc =
    ((DesignerActionUIService)(GetService(typeof(DesignerActionUIService))));
    }

    #endregion

    #region Public Methods (Overrides)

    // This method populates the actual Smart Tag form. If you wish to
    change the
    // order that the properties appear in, this is the place to do so.

    /// <summary>
    /// Returns the collection of <see
    cref="T:System.ComponentModel.Design.DesignerActionItem"></see> objects
    contained in the list.
    /// </summary>
    /// <returns>
    /// A <see
    cref="T:System.ComponentModel.Design.DesignerActionItem"></see> array that
    contains the items in this list.
    /// </returns>
    public override DesignerActionItemCollection GetSortedActionItems()
    {
    DesignerActionItemCollection items = new
    DesignerActionItemCollection();
    items.Add(new DesignerActionHeaderItem("Callback"));
    items.Add(new DesignerActionTextItem("Adjusts the AJAX
    functionality of this control", "Callback"));
    items.Add(new DesignerActionPropertyItem("CallbackEnabled",
    "Callback Enabled", "Callback", "Whether callback is enabled to this control
    or not."));
    items.Add(new DesignerActionPropertyItem("DisableAtCallback",
    "Disabled At Callback", "Callback", "Whether this control should be disabled
    on the form while a callback is in process."));
    items.Add(new DesignerActionPropertyItem("AutoPostback",
    "AutoPostback", "Callback", "Whether this control causes postback as soon as
    it is checked or unchecked (only relevant if Callback is disabled)."));
    items.Add(new DesignerActionPropertyItem("ScriptsPath", "Scripts
    Path", "Callback", "The relative path of the location where the JavaScript
    files are stores (ex. '~/Scripts/')."));
    items.Add(new DesignerActionHeaderItem("Required Field
    Validator"));
    items.Add(new DesignerActionTextItem("Determines whether this
    control is mandatory or not.", "Required Field Validator"));
    items.Add(new DesignerActionPropertyItem("Required", "Required",
    "Required Field Validator", "Whether this is a 'Required' field or not."));
    items.Add(new DesignerActionPropertyItem("WarningIconVisible",
    "Warning Icon Visible", "Required Field Validator", "Whether the warning icon
    is displayed or not (should be true when a validation error occurs)."));
    items.Add(new DesignerActionPropertyItem("WarningImageUrl",
    "Warning Image Url", "Required Field Validator", "The path/URL of the image
    to display when a validation error is raised."));
    items.Add(new DesignerActionPropertyItem("EmptyImageUrl", "Empty
    Image Url", "Required Field Validator", "The path/URL of the image to display
    when no error is present."));
    items.Add(new DesignerActionPropertyItem("ImageAlign", "Image
    Align", "Required Field Validator", "The way the image is aligned on the
    screen, relative to the label text."));
    items.Add(new DesignerActionPropertyItem("MessageStyle",
    "Message Style", "Required Field Validator", "The type of message that is
    display when the user clicks on or mouses over the warning icon."));
    items.Add(new DesignerActionTextItem("Settings pertaining to the
    'PopupMessage' Message Style", "PopupMessage"));
    items.Add(new DesignerActionPropertyItem("MessageText",
    "Message", "PopupMessage", "The body message to display in the popup
    window."));
    items.Add(new
    DesignerActionPropertyItem("MessageTextResourceKey", "Message Resource Key",
    "PopupMessage", "The resource key for the popup window's body message."));
    items.Add(new DesignerActionPropertyItem("MessageTitle",
    "Title", "PopupMessage", "The title of the message to display in the popup
    window."));
    items.Add(new
    DesignerActionPropertyItem("MessageTitleResourceKey", "Title Resource Key",
    "PopupMessage", "The resource key for the popup window's title."));
    items.Add(new DesignerActionTextItem("Settings pertaining to the
    'UriLink' Message Style", "URI Link"));
    items.Add(new DesignerActionPropertyItem("LinkUrl", "Link URL",
    "URI Link", "The URL to open in a new window when the user clicks the warning
    icon."));
    return items;
    }

    #endregion

    #region Private Methods

    // The properties of a custom control must be set through a proxy
    property.
    // If they are modified directly, such as setting the "Text" item in
    the Smart
    // Tag to some string such as "OK," the Properties window will not
    reflect the
    // changes. Therefore the properties must be set through a proxy,
    such as through
    // the method below.

    /// <summary>
    /// Gets a PropertyDescriptor for one of the control's properties
    based on its name.
    /// This is necessary because properties must be set in the designer
    by means a 'proxy'.
    /// </summary>
    /// <param name="propName">Full name of the property.</param>
    /// <returns></returns>
    private PropertyDescriptor GetPropertyByName(string propName)
    {
    PropertyDescriptor prop;
    prop = TypeDescriptor.GetProperties(m_checkBox)[propName];
    if (prop == null)
    {
    throw new ArgumentException("Property invalid.", propName);
    }
    else
    {
    return prop;
    }
    }

    #endregion

    #region Public Properties

    // All properties that need to be manipulated within the Smart Tag
    need to
    // have wrappers. The 'wrapper properties, seen below, are passed
    to the
    // parent control by means of the GetPropertyByName method (defined
    in this
    // class). The reason for this is detailed in the comments for the
    // GetPropertyByName method above.

    /// <summary>
    /// A wrapper that points to the control's ScriptPath property
    /// </summary>
    /// <value>The scripts path.</value>
    public string ScriptsPath
    {
    get
    {
    return m_checkBox.ScriptsPath;
    }
    set
    {
    GetPropertyByName("ScriptsPath").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's CallbackEnabled property
    /// </summary>
    /// <value><c>true</c> if callback is enabled; otherwise,
    <c>false</c>.</value>
    public bool CallbackEnabled
    {
    get
    {
    return m_checkBox.CallbackEnabled;
    }
    set
    {
    GetPropertyByName("CallbackEnabled").SetValue(m_checkBox,
    value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's AutoPostback property
    /// </summary>
    /// <value><c>true</c> if AutoPostback is enabled; otherwise,
    <c>false</c>.</value>
    public bool AutoPostback
    {
    get
    {
    return m_checkBox.AutoPostback;
    }
    set
    {
    GetPropertyByName("AutoPostback").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's DisableAtCallback property
    /// </summary>
    /// <value><c>true</c> if disabled during callback; otherwise,
    <c>false</c>.</value>
    public bool DisableAtCallback
    {
    get
    {
    return this.m_checkBox.DisableAtCallback;
    }
    set
    {
    GetPropertyByName("DisableAtCallback").SetValue(m_checkBox,
    value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's Required property
    /// </summary>
    /// <value><c>true</c> if required; otherwise, <c>false</c>.</value>
    public bool Required
    {
    get
    {
    return m_checkBox.Required;
    }
    set
    {
    GetPropertyByName("Required").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's WarningImageUrl property
    /// </summary>
    /// <value>The image URL.</value>
    [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design,
    Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    typeof(UITypeEditor))]
    public string WarningImageUrl
    {
    get
    {
    return m_checkBox.WarningImageUrl;
    }
    set
    {
    GetPropertyByName("WarningImageUrl").SetValue(m_checkBox,
    value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's EmptyImageUrl property
    /// </summary>
    /// <value>The empty image URL.</value>
    [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design,
    Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    typeof(UITypeEditor))]
    public string EmptyImageUrl
    {
    get
    {
    return m_checkBox.EmptyImageUrl;
    }
    set
    {
    GetPropertyByName("EmptyImageUrl").SetValue(m_checkBox,
    value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's ImageAlign property
    /// </summary>
    /// <value>The image align.</value>
    public ImageAlign ImageAlign
    {
    get
    {
    return m_checkBox.ImageAlign;
    }
    set
    {
    GetPropertyByName("ImageAlign").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's MessageStyle property
    /// </summary>
    /// <value>The message style.</value>
    public MessageStyle MessageStyle
    {
    get
    {
    return m_checkBox.MessageStyle;
    }
    set
    {
    GetPropertyByName("MessageStyle").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's MessageText property
    /// </summary>
    /// <value>The message text.</value>
    public string MessageText
    {
    get
    {
    return m_checkBox.PopupText;
    }
    set
    {
    GetPropertyByName("PopupText").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's MessageTextResourceKey
    property
    /// </summary>
    /// <value>The message text resource key.</value>
    public string MessageTextResourceKey
    {
    get
    {
    return m_checkBox.PopupTextResourceKey;
    }
    set
    {

    GetPropertyByName("PopupTextResourceKey").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's MessageTitle property
    /// </summary>
    /// <value>The message title.</value>
    public string MessageTitle
    {
    get
    {
    return m_checkBox.PopupTitle;
    }
    set
    {
    GetPropertyByName("PopupTitle").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's MessageTitleResourceKey
    property
    /// </summary>
    /// <value>The message title resource key.</value>
    public string MessageTitleResourceKey
    {
    get
    {
    return m_checkBox.PopupTitleResourceKey;
    }
    set
    {

    GetPropertyByName("PopupTitleResourceKey").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's LinkUrl property
    /// </summary>
    /// <value>The link URL.</value>
    [Editor("System.Web.UI.Design.UrlEditor, System.Design,
    Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    typeof(UITypeEditor))]
    public string LinkUrl
    {
    get
    {
    return m_checkBox.LinkUrl;
    }
    set
    {
    GetPropertyByName("LinkUrl").SetValue(m_checkBox, value);
    }
    }

    /// <summary>
    /// A wrapper that points to the control's WarningIconVisible property
    /// </summary>
    /// <value><c>true</c> if warning icon is visible; otherwise,
    <c>false</c>.</value>
    public bool WarningIconVisible
    {
    get
    {
    return m_checkBox.WarningIconVisible;
    }
    set
    {
    GetPropertyByName("WarningIconVisible").SetValue(m_checkBox,
    value);
    }
    }

    #endregion
    }

    #endregion

    }
    Christophe Peillet, Jan 9, 2006
    #2
    1. Advertising

  3. RE: Designer Code for this control

    Hi ChristophePeillet,

    Welcome to ASPNET newsgroup.
    As for the custom webserver control's property value changing being
    reflected in designview quesiton, here are some of my understanding and
    suggestions:

    As for Properteis in WebServer Control which related to UI or states of
    inner controls, we suggest that we store them in a private member field or
    directly associated with a ViewState key rather than directly expose the
    inner control's Property to them. And in the custom control's code, we can
    always put the applying styles or properteis work in PreRender event (or
    OnPreRender method) since this is the last place we can change control
    states and at that time we can ensure that the control structure has been
    well constructed.

    And for design-time HTML rendering, we suggest that we separate them from
    teh runtime rendering code, since for Composite control should put as much
    code in CreateChildControls as possible(avoid put code in Render
    method....).... Since you can provide a custom Control designer for our
    custom control, just override the GetDesignTimeHtml method which helps
    define our custom design-time html of our custom webcontrol:

    To make the above clear, here is a simple control which expose a BackColor
    property for inner textbox sub controls and I persist it in viewstate and
    at design-time, when I change the property in property grid, the
    design-time html (I use GetDesignTimeHtml method to generate design-time
    html) will refresh to reflect the chagne:


    namespace WebControlLib
    {

    [ToolboxData("<{0}:ColorTextBox runat=server></{0}:ColorTextBox>")]
    [Designer(typeof(ColorTextBoxDesigner), typeof(IDesigner))]
    [ParseChildren(true)]
    public class ColorTextBox : WebControl, INamingContainer
    {
    private TextBox _txt;


    [Browsable(true),
    TypeConverter(typeof(WebColorConverter)),
    DefaultValue(typeof(Color), "White")]
    public Color TextBoxBackColor
    {
    get
    {
    object clr =ViewState["txtbgcolor"];
    if (clr != null)
    {
    return (Color)clr;
    }

    return Color.White;

    }

    set
    {
    ViewState["txtbgcolor"] = value;
    }
    }

    protected override void CreateChildControls()
    {
    Controls.Clear();

    Table tbMain = new Table();
    tbMain.ID = "tbMain";
    tbMain.Width = System.Web.UI.WebControls.Unit.Percentage(100);
    tbMain.BorderStyle = BorderStyle.Solid;
    tbMain.BorderWidth = 1;

    tbMain.Rows.Add(new TableRow());
    tbMain.Rows[0].Cells.Add(new TableCell());

    Controls.Add(tbMain);

    _txt = new TextBox();
    _txt.ID = "txtMain";
    _txt.TextChanged += new EventHandler(txt_TextChanged);

    tbMain.Rows[0].Cells[0].Controls.Add(_txt);

    }

    protected override void OnPreRender(EventArgs e)
    {
    base.OnPreRender(e);

    _txt.BackColor = TextBoxBackColor;
    }


    protected override void RenderContents(HtmlTextWriter output)
    {
    RenderChildren(output);
    }



    private void txt_TextChanged(object sender, EventArgs e)
    {
    Page.Response.Write("<br>Text: " + ((TextBox)sender).Text);
    }
    }


    public class ColorTextBoxDesigner : ControlDesigner
    {
    public override string GetDesignTimeHtml()
    {
    ColorTextBox colortxt = this.Component as ColorTextBox;


    StringBuilder sb = new StringBuilder();
    sb.Append("<font size='30' red='red'>");
    sb.Append("ColorTextBox,BackColor: " +
    colortxt.TextBoxBackColor);
    sb.Append("</font>");

    return sb.ToString();
    }


    }
    }


    Hope helps. Thanks,

    Steven Cheng
    Microsoft Online Support

    Get Secure! www.microsoft.com/security
    (This posting is provided "AS IS", with no warranties, and confers no
    rights.)


    --------------------
    | Thread-Topic: Designer Code for this control
    | thread-index: AcYU/OQFbs8UjYBfQoWWNss8rEWDRA==
    | X-WBNR-Posting-Host: 193.172.19.20
    | From: =?Utf-8?B?Q2hyaXN0b3BoZSBQZWlsbGV0?=
    <>
    | References: <>
    | Subject: Designer Code for this control
    | Date: Mon, 9 Jan 2006 01:13:01 -0800
    | Lines: 505
    | Message-ID: <>
    | MIME-Version: 1.0
    | Content-Type: text/plain;
    | charset="Utf-8"
    | Content-Transfer-Encoding: 7bit
    | X-Newsreader: Microsoft CDO for Windows 2000
    | Content-Class: urn:content-classes:message
    | Importance: normal
    | Priority: normal
    | X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
    | Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
    | NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 10.40.2.250
    | Path: TK2MSFTNGXA02.phx.gbl!TK2MSFTNGXA01.phx.gbl!TK2MSFTNGXA03.phx.gbl
    | Xref: TK2MSFTNGXA02.phx.gbl
    microsoft.public.dotnet.framework.aspnet.webcontrols:32325
    | X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
    |
    | Here is the Designer code for this control:
    |
    | using System;
    | 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 System.Drawing.Design;
    | using Telerik.WebControls;
    |
    | namespace CompanyName.EEE.Web.UI.FormControls
    | {
    |
    | #region Support CheckBox Designer
    |
    | // This designer class manages the control's Smart Tags, including any
    | // properties and actions exposed within then. This particular class
    | // serves as more of a 'manager', since most of the actual work takes
    | // place in the class below that inherits from DesignerActionList.
    |
    | /// <summary>
    | /// The designer used by <see cref="T:SupportCheckBox"></see> to add
    | DesignMode functionality
    | /// (such as SmartTags) to the Visual Studio 2005 IDE.
    | /// </summary>
    | /// <seealso cref="T:SupportTextBoxActionList"/>
    | public class SupportCheckBoxDesigner : CompositeControlDesigner
    | {
    | #region Private Fields
    |
    | private DesignerActionListCollection lists;
    |
    | #endregion
    |
    | #region Public Methods (Overrides)
    |
    | /// <summary>
    | /// Gets the action list collection for the control designer.
    | /// </summary>
    | /// <value></value>
    | /// <returns>A <see
    | cref="T:System.ComponentModel.Design.DesignerActionListCollection"></see>
    | that contains the <see
    | cref="T:System.ComponentModel.Design.DesignerActionList"></see> items for
    the
    | control designer.</returns>
    | public override DesignerActionListCollection ActionLists
    | {
    | get
    | {
    | if (lists == null)
    | {
    | lists = new DesignerActionListCollection();
    | lists.Add(new
    SupportCheckBoxActionList(this.Component));
    | }
    | return lists;
    | }
    | }
    |
    | #endregion
    | }
    |
    | #endregion
    |
    | #region Support CheckBox Action List
    |
    | // The inherited DesignerActionList class is designed to associate
    one
    | or more
    | // designer action items with a single component. Most of the actual
    | DesignMode
    | // and Smart Tag work takes place here.
    |
    | /// <summary>
    | /// Associates one or more action items with the <see
    | cref="T:SupportCheckBox"></see> Designer.
    | /// </summary>
    | /// <seealso cref="T:SupportCheckBoxDesigner"/>
    | public class SupportCheckBoxActionList : DesignerActionList
    | {
    | #region Private Fields
    |
    | private SupportCheckBox m_checkBox;
    | private DesignerActionUIService designerActionSvc = null;
    |
    | #endregion
    |
    | #region Constructors
    |
    | /// <summary>
    | /// Initializes a new instance of the <see
    | cref="SupportCheckBoxActionList"/> class.
    | /// </summary>
    | /// <param name="component">A component related to the <see
    | cref="T:System.ComponentModel.Design.DesignerActionList"></see>.</param>
    | public SupportCheckBoxActionList(IComponent component)
    | : base(component)
    | {
    | this.m_checkBox = (SupportCheckBox)component;
    | this.designerActionSvc =
    | ((DesignerActionUIService)(GetService(typeof(DesignerActionUIService))));
    | }
    |
    | #endregion
    |
    | #region Public Methods (Overrides)
    |
    | // This method populates the actual Smart Tag form. If you wish
    to
    | change the
    | // order that the properties appear in, this is the place to do
    so.
    |
    | /// <summary>
    | /// Returns the collection of <see
    | cref="T:System.ComponentModel.Design.DesignerActionItem"></see> objects
    | contained in the list.
    | /// </summary>
    | /// <returns>
    | /// A <see
    | cref="T:System.ComponentModel.Design.DesignerActionItem"></see> array
    that
    | contains the items in this list.
    | /// </returns>
    | public override DesignerActionItemCollection
    GetSortedActionItems()
    | {
    | DesignerActionItemCollection items = new
    | DesignerActionItemCollection();
    | items.Add(new DesignerActionHeaderItem("Callback"));
    | items.Add(new DesignerActionTextItem("Adjusts the AJAX
    | functionality of this control", "Callback"));
    | items.Add(new DesignerActionPropertyItem("CallbackEnabled",
    | "Callback Enabled", "Callback", "Whether callback is enabled to this
    control
    | or not."));
    | items.Add(new DesignerActionPropertyItem("DisableAtCallback",
    | "Disabled At Callback", "Callback", "Whether this control should be
    disabled
    | on the form while a callback is in process."));
    | items.Add(new DesignerActionPropertyItem("AutoPostback",
    | "AutoPostback", "Callback", "Whether this control causes postback as soon
    as
    | it is checked or unchecked (only relevant if Callback is disabled)."));
    | items.Add(new DesignerActionPropertyItem("ScriptsPath",
    "Scripts
    | Path", "Callback", "The relative path of the location where the
    JavaScript
    | files are stores (ex. '~/Scripts/')."));
    | items.Add(new DesignerActionHeaderItem("Required Field
    | Validator"));
    | items.Add(new DesignerActionTextItem("Determines whether this
    | control is mandatory or not.", "Required Field Validator"));
    | items.Add(new DesignerActionPropertyItem("Required",
    "Required",
    | "Required Field Validator", "Whether this is a 'Required' field or
    not."));
    | items.Add(new
    DesignerActionPropertyItem("WarningIconVisible",
    | "Warning Icon Visible", "Required Field Validator", "Whether the warning
    icon
    | is displayed or not (should be true when a validation error occurs)."));
    | items.Add(new DesignerActionPropertyItem("WarningImageUrl",
    | "Warning Image Url", "Required Field Validator", "The path/URL of the
    image
    | to display when a validation error is raised."));
    | items.Add(new DesignerActionPropertyItem("EmptyImageUrl",
    "Empty
    | Image Url", "Required Field Validator", "The path/URL of the image to
    display
    | when no error is present."));
    | items.Add(new DesignerActionPropertyItem("ImageAlign", "Image
    | Align", "Required Field Validator", "The way the image is aligned on the
    | screen, relative to the label text."));
    | items.Add(new DesignerActionPropertyItem("MessageStyle",
    | "Message Style", "Required Field Validator", "The type of message that is
    | display when the user clicks on or mouses over the warning icon."));
    | items.Add(new DesignerActionTextItem("Settings pertaining to
    the
    | 'PopupMessage' Message Style", "PopupMessage"));
    | items.Add(new DesignerActionPropertyItem("MessageText",
    | "Message", "PopupMessage", "The body message to display in the popup
    | window."));
    | items.Add(new
    | DesignerActionPropertyItem("MessageTextResourceKey", "Message Resource
    Key",
    | "PopupMessage", "The resource key for the popup window's body message."));
    | items.Add(new DesignerActionPropertyItem("MessageTitle",
    | "Title", "PopupMessage", "The title of the message to display in the
    popup
    | window."));
    | items.Add(new
    | DesignerActionPropertyItem("MessageTitleResourceKey", "Title Resource
    Key",
    | "PopupMessage", "The resource key for the popup window's title."));
    | items.Add(new DesignerActionTextItem("Settings pertaining to
    the
    | 'UriLink' Message Style", "URI Link"));
    | items.Add(new DesignerActionPropertyItem("LinkUrl", "Link
    URL",
    | "URI Link", "The URL to open in a new window when the user clicks the
    warning
    | icon."));
    | return items;
    | }
    |
    | #endregion
    |
    | #region Private Methods
    |
    | // The properties of a custom control must be set through a proxy
    | property.
    | // If they are modified directly, such as setting the "Text" item
    in
    | the Smart
    | // Tag to some string such as "OK," the Properties window will
    not
    | reflect the
    | // changes. Therefore the properties must be set through a proxy,
    | such as through
    | // the method below.
    |
    | /// <summary>
    | /// Gets a PropertyDescriptor for one of the control's properties
    | based on its name.
    | /// This is necessary because properties must be set in the
    designer
    | by means a 'proxy'.
    | /// </summary>
    | /// <param name="propName">Full name of the property.</param>
    | /// <returns></returns>
    | private PropertyDescriptor GetPropertyByName(string propName)
    | {
    | PropertyDescriptor prop;
    | prop = TypeDescriptor.GetProperties(m_checkBox)[propName];
    | if (prop == null)
    | {
    | throw new ArgumentException("Property invalid.",
    propName);
    | }
    | else
    | {
    | return prop;
    | }
    | }
    |
    | #endregion
    |
    | #region Public Properties
    |
    | // All properties that need to be manipulated within the Smart
    Tag
    | need to
    | // have wrappers. The 'wrapper properties, seen below, are
    passed
    | to the
    | // parent control by means of the GetPropertyByName method
    (defined
    | in this
    | // class). The reason for this is detailed in the comments for
    the
    | // GetPropertyByName method above.
    |
    | /// <summary>
    | /// A wrapper that points to the control's ScriptPath property
    | /// </summary>
    | /// <value>The scripts path.</value>
    | public string ScriptsPath
    | {
    | get
    | {
    | return m_checkBox.ScriptsPath;
    | }
    | set
    | {
    | GetPropertyByName("ScriptsPath").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's CallbackEnabled
    property
    | /// </summary>
    | /// <value><c>true</c> if callback is enabled; otherwise,
    | <c>false</c>.</value>
    | public bool CallbackEnabled
    | {
    | get
    | {
    | return m_checkBox.CallbackEnabled;
    | }
    | set
    | {
    | GetPropertyByName("CallbackEnabled").SetValue(m_checkBox,
    | value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's AutoPostback property
    | /// </summary>
    | /// <value><c>true</c> if AutoPostback is enabled; otherwise,
    | <c>false</c>.</value>
    | public bool AutoPostback
    | {
    | get
    | {
    | return m_checkBox.AutoPostback;
    | }
    | set
    | {
    | GetPropertyByName("AutoPostback").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's DisableAtCallback
    property
    | /// </summary>
    | /// <value><c>true</c> if disabled during callback; otherwise,
    | <c>false</c>.</value>
    | public bool DisableAtCallback
    | {
    | get
    | {
    | return this.m_checkBox.DisableAtCallback;
    | }
    | set
    | {
    |
    GetPropertyByName("DisableAtCallback").SetValue(m_checkBox,
    | value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's Required property
    | /// </summary>
    | /// <value><c>true</c> if required; otherwise,
    <c>false</c>.</value>
    | public bool Required
    | {
    | get
    | {
    | return m_checkBox.Required;
    | }
    | set
    | {
    | GetPropertyByName("Required").SetValue(m_checkBox, value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's WarningImageUrl
    property
    | /// </summary>
    | /// <value>The image URL.</value>
    | [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design,
    | Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    | typeof(UITypeEditor))]
    | public string WarningImageUrl
    | {
    | get
    | {
    | return m_checkBox.WarningImageUrl;
    | }
    | set
    | {
    | GetPropertyByName("WarningImageUrl").SetValue(m_checkBox,
    | value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's EmptyImageUrl property
    | /// </summary>
    | /// <value>The empty image URL.</value>
    | [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design,
    | Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    | typeof(UITypeEditor))]
    | public string EmptyImageUrl
    | {
    | get
    | {
    | return m_checkBox.EmptyImageUrl;
    | }
    | set
    | {
    | GetPropertyByName("EmptyImageUrl").SetValue(m_checkBox,
    | value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's ImageAlign property
    | /// </summary>
    | /// <value>The image align.</value>
    | public ImageAlign ImageAlign
    | {
    | get
    | {
    | return m_checkBox.ImageAlign;
    | }
    | set
    | {
    | GetPropertyByName("ImageAlign").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's MessageStyle property
    | /// </summary>
    | /// <value>The message style.</value>
    | public MessageStyle MessageStyle
    | {
    | get
    | {
    | return m_checkBox.MessageStyle;
    | }
    | set
    | {
    | GetPropertyByName("MessageStyle").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's MessageText property
    | /// </summary>
    | /// <value>The message text.</value>
    | public string MessageText
    | {
    | get
    | {
    | return m_checkBox.PopupText;
    | }
    | set
    | {
    | GetPropertyByName("PopupText").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's MessageTextResourceKey
    | property
    | /// </summary>
    | /// <value>The message text resource key.</value>
    | public string MessageTextResourceKey
    | {
    | get
    | {
    | return m_checkBox.PopupTextResourceKey;
    | }
    | set
    | {
    |
    | GetPropertyByName("PopupTextResourceKey").SetValue(m_checkBox, value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's MessageTitle property
    | /// </summary>
    | /// <value>The message title.</value>
    | public string MessageTitle
    | {
    | get
    | {
    | return m_checkBox.PopupTitle;
    | }
    | set
    | {
    | GetPropertyByName("PopupTitle").SetValue(m_checkBox,
    value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's
    MessageTitleResourceKey
    | property
    | /// </summary>
    | /// <value>The message title resource key.</value>
    | public string MessageTitleResourceKey
    | {
    | get
    | {
    | return m_checkBox.PopupTitleResourceKey;
    | }
    | set
    | {
    |
    | GetPropertyByName("PopupTitleResourceKey").SetValue(m_checkBox, value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's LinkUrl property
    | /// </summary>
    | /// <value>The link URL.</value>
    | [Editor("System.Web.UI.Design.UrlEditor, System.Design,
    | Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    | typeof(UITypeEditor))]
    | public string LinkUrl
    | {
    | get
    | {
    | return m_checkBox.LinkUrl;
    | }
    | set
    | {
    | GetPropertyByName("LinkUrl").SetValue(m_checkBox, value);
    | }
    | }
    |
    | /// <summary>
    | /// A wrapper that points to the control's WarningIconVisible
    property
    | /// </summary>
    | /// <value><c>true</c> if warning icon is visible; otherwise,
    | <c>false</c>.</value>
    | public bool WarningIconVisible
    | {
    | get
    | {
    | return m_checkBox.WarningIconVisible;
    | }
    | set
    | {
    |
    GetPropertyByName("WarningIconVisible").SetValue(m_checkBox,
    | value);
    | }
    | }
    |
    | #endregion
    | }
    |
    | #endregion
    |
    | }
    |
    |
    Steven Cheng[MSFT], Jan 10, 2006
    #3
  4. Updated Code

    Steven:

    Thank you for your response.

    I normally place the value of properties in the ViewState, but in this case,
    I choose to access the control's properties directly, since the underlying
    control also adds it's value to the ViewState. I would be storing the
    Textbox's 'Text' value in ViewState twice if I also added it here in this
    composite control.

    As per your advice, I have rearranged some of the code, and tried to remove
    everything from the Render event, instead pushing pushing the relevant code
    into CreateChildControls(). I have also moved the code where property values
    are assigned to OnPreRender(), rather than the private SetRunTimeProperties().

    For simplicity sake, I have also removed the custom designer. I have
    included the full modified class below.

    Unfortunately, my problem still persists. Whenever I make a change to any
    of my custom properties (such as LabelText, which is defined in the parent
    class, or TextboxText, which is defined in this class), these values are
    changed in the underlying HTML code and appear at run time, but never change
    in DesignMode and the Property Browser is never updated. This makes it
    almost impossible to meaningfully create controls at DesignTime.

    If I place some sort of rendering code in a Designer in the
    'GetDesignTimeHtml()' method, does it mean I will need to duplicate all of my
    rendering code in the Designer as well (I hate to have the same code in two
    places)? The control should work without a designer at all, though,
    shouldn't it? (I only created one to allow SmartTags support.)

    If you can give me any other advice on why control's are not being refreshed
    at DesignTime, it would be appreciated. I'm completely lost with this
    problem, and am already behind schedule because of it. ;-(

    Best regards, and thank you for your time.

    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"/>
    // ToDo: Restore Designer
    // [Designer(typeof(SupportTextBoxDesigner))]
    [DefaultProperty("Text")]
    [DefaultEvent("TextChanged")]
    [ToolboxData("<{0}:SupportTextBox runat=server></{0}:SupportTextBox>")]
    public class SupportTextBox : SupportFormLabelledControl, INamingContainer
    {
    #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)
    {
    // Call base Load method
    base.OnLoad(e);

    EnsureChildControls();
    }

    /// <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
    Table tbl = new Table();
    m_txt = new CallbackTextBox();
    m_lbl = new CallbackLabel();
    m_icn = new IconPopupControl();

    // Register any events associated with dependant controls
    m_txt.TextChanged += new EventHandler(RaiseTextChanged);

    // Create table object and format it through relevant method
    tbl = CreateTable(this.LabelPosition);

    // Add table to the control collection
    Controls.Add(tbl);

    // Add controls to the table control collection
    switch (this.LabelPosition)
    {
    case Position.Left:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[0].Cells[1].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[0].Cells[1].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Top:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[1].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[1].Cells[0].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Right:
    tbl.Rows[0].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[0].Cells[0].Controls.Add(m_icn);
    }
    tbl.Rows[0].Cells[1].Controls.Add(m_lbl);
    // Set relevant design properties
    tbl.Rows[0].Cells[1].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Bottom:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[1].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[1].Cells[1].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    default:
    Debug.Assert(false);
    break;
    }

    // Call base method
    base.CreateChildControls();
    }

    /// <summary>
    /// Raises the <see cref="E:System.Web.UI.Control.PreRender"></see>
    event.
    /// </summary>
    /// <param name="e">An <see cref="T:System.EventArgs"></see> object
    that contains the event data.</param>
    protected override void OnPreRender(EventArgs e)
    {
    base.OnPreRender(e);

    // 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;
    }

    /// <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();

    // Create temporary HtmlTextWriter placeholder
    StringBuilder stringBuilder = new StringBuilder();
    StringWriter stringWriter = new StringWriter(stringBuilder);
    HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

    // Render child controls
    RenderChildren(htmlWriter);

    // 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 RaiseTextChanged(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>
    /// Creates the table that will hold the relevant controls.
    /// </summary>
    /// <param name="labelPosition">The label position, which is used to
    /// determine how the table should be arranged.</param>
    /// <returns>A Table object</returns>
    private Table CreateTable(Position labelPosition)
    {
    Table tbl = new Table();

    // Set basic table properties
    tbl.BorderStyle = BorderStyle.None;
    tbl.BorderWidth = 0;

    // Format table according to label position
    switch (labelPosition)
    {
    case Position.Left:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows[0].Cells.Add(new TableCell());
    break;
    case Position.Top:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows.Add(new TableRow());
    tbl.Rows[1].Cells.Add(new TableCell());
    break;
    case Position.Right:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows[0].Cells.Add(new TableCell());
    break;
    case Position.Bottom:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows.Add(new TableRow());
    tbl.Rows[1].Cells.Add(new TableCell());
    break;
    default:
    Debug.Assert(false);
    break;
    }

    // Return results
    return tbl;
    }

    #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
    {
    EnsureChildControls();
    return m_txt.CssClass;
    }
    set
    {
    Debug.Assert(value != null, "Warning: TextboxCssClass
    property is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_txt.CssClass = 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
    {
    EnsureChildControls();
    return m_txt.ReadOnly;
    }
    set
    {
    EnsureChildControls();
    m_txt.ReadOnly = 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)]
    [NotifyParentProperty(true)]
    public string TextboxText
    {
    get
    {
    EnsureChildControls();
    return m_txt.Text;
    }
    set
    {
    Debug.Assert(value != null, "Warning: TextboxText property
    is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_txt.Text = value;
    }
    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
    {
    EnsureChildControls();
    return m_txt.MaxLength;
    }
    set
    {
    EnsureChildControls();
    m_txt.MaxLength = value;
    }
    }

    #endregion

    }
    }
    Christophe Peillet, Jan 10, 2006
    #4
  5. RE: Designer Code for this control

    Steven:

    I have made some of the modifications you mentionned, such as moving code
    out of the Render method, and into the CreateChildControls() method. I've
    also pushed some code into OnPreRender(), rather than using the private
    method SetRunTimeProperties(). For testing purposes, I've also disabled the
    designer altogether (I only implemented it to allow SmartTags support).

    As to the properties not being stored in a local field and persisted into
    ViewState, I access them directly because the child controls themselves
    persist this information to ViewState. If I also added my 'TextboxText'
    property to ViewState, I would essentially be adding the same piece of
    information twice. In the parent class (SupportFormLabelledControl), I do
    place all custom (unique) variables in ViewState.

    Unfortunately, after making some of the changes you mentionned, I still have
    the same problem. When I make a change to any of my custom properties (such
    as TextboxText in this class, or LabelText in the parent class), the changes
    are added to the underlying Html code and appear at RunTime, but are never
    reflected in DesignMode, make the controls almost useless for the developers
    who will use them. I don't believe that it is mandatory to make a designer
    for every custom control, just to update properties at DesignTime, is it?
    (That seems like a lot of work for something that should be simple?). I
    suspect the problem is more than I am doing something in the wrong place, and
    so the properties are not being updated, or not
    'UpdateMyPropertiesAnReRender' sort of event is being fired, etc.

    I'm really terribly behing schedule on finishing these controls, but just
    can't find the problem. (This is the first problem I've really had to go to
    the forums for, since I couldn't find any solutions through Google.) Any
    help you can offer will really be enourmously appreciated. The full updated
    code for one of the controls is located below. If you would like the parent
    class let me know. Thank you again for your help on this.

    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 CompanyName.EEE.Web.UI.FormControls
    {
    /// <summary>
    /// An AJAX enabled TextBox control, which automatically applies the
    CompanyName style guide to its appearance.
    /// </summary>
    /// <seealso cref="T:SupportTextBoxDesigner"/>
    /// <seealso cref="T:SupportTextBoxActionList"/>
    // ToDo: Restore Designer
    // [Designer(typeof(SupportTextBoxDesigner))]
    [DefaultProperty("Text")]
    [DefaultEvent("TextChanged")]
    [ToolboxData("<{0}:SupportTextBox runat=server></{0}:SupportTextBox>")]
    public class SupportTextBox : SupportFormLabelledControl, INamingContainer
    {
    #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)
    {
    // Call base Load method
    base.OnLoad(e);

    EnsureChildControls();
    }

    /// <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
    Table tbl = new Table();
    m_txt = new CallbackTextBox();
    m_lbl = new CallbackLabel();
    m_icn = new IconPopupControl();

    // Register any events associated with dependant controls
    m_txt.TextChanged += new EventHandler(RaiseTextChanged);

    // Create table object and format it through relevant method
    tbl = CreateTable(this.LabelPosition);

    // Add table to the control collection
    Controls.Add(tbl);

    // Add controls to the table control collection
    switch (this.LabelPosition)
    {
    case Position.Left:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[0].Cells[1].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[0].Cells[1].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Top:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[1].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[1].Cells[0].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Right:
    tbl.Rows[0].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[0].Cells[0].Controls.Add(m_icn);
    }
    tbl.Rows[0].Cells[1].Controls.Add(m_lbl);
    // Set relevant design properties
    tbl.Rows[0].Cells[1].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    case Position.Bottom:
    tbl.Rows[0].Cells[0].Controls.Add(m_lbl);
    tbl.Rows[1].Cells[0].Controls.Add(m_txt);
    if (this.Required)
    {
    tbl.Rows[1].Cells[1].Controls.Add(m_icn);
    }
    // Set relevant design properties
    tbl.Rows[0].Cells[0].Width = new
    Unit(this.LabelWidth.ToString());
    break;
    default:
    Debug.Assert(false);
    break;
    }

    // Call base method
    base.CreateChildControls();
    }

    /// <summary>
    /// Raises the <see cref="E:System.Web.UI.Control.PreRender"></see>
    event.
    /// </summary>
    /// <param name="e">An <see cref="T:System.EventArgs"></see> object
    that contains the event data.</param>
    protected override void OnPreRender(EventArgs e)
    {
    base.OnPreRender(e);

    // 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;
    }

    /// <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();

    // Create temporary HtmlTextWriter placeholder
    StringBuilder stringBuilder = new StringBuilder();
    StringWriter stringWriter = new StringWriter(stringBuilder);
    HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

    // Render child controls
    RenderChildren(htmlWriter);

    // 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 RaiseTextChanged(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>
    /// Creates the table that will hold the relevant controls.
    /// </summary>
    /// <param name="labelPosition">The label position, which is used to
    /// determine how the table should be arranged.</param>
    /// <returns>A Table object</returns>
    private Table CreateTable(Position labelPosition)
    {
    Table tbl = new Table();

    // Set basic table properties
    tbl.BorderStyle = BorderStyle.None;
    tbl.BorderWidth = 0;

    // Format table according to label position
    switch (labelPosition)
    {
    case Position.Left:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows[0].Cells.Add(new TableCell());
    break;
    case Position.Top:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows.Add(new TableRow());
    tbl.Rows[1].Cells.Add(new TableCell());
    break;
    case Position.Right:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows[0].Cells.Add(new TableCell());
    break;
    case Position.Bottom:
    tbl.Rows.Add(new TableRow());
    tbl.Rows[0].Cells.Add(new TableCell());
    tbl.Rows.Add(new TableRow());
    tbl.Rows[1].Cells.Add(new TableCell());
    break;
    default:
    Debug.Assert(false);
    break;
    }

    // Return results
    return tbl;
    }

    #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
    {
    EnsureChildControls();
    return m_txt.CssClass;
    }
    set
    {
    Debug.Assert(value != null, "Warning: TextboxCssClass
    property is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_txt.CssClass = 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
    {
    EnsureChildControls();
    return m_txt.ReadOnly;
    }
    set
    {
    EnsureChildControls();
    m_txt.ReadOnly = 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)]
    [NotifyParentProperty(true)]
    public string TextboxText
    {
    get
    {
    EnsureChildControls();
    return m_txt.Text;
    }
    set
    {
    Debug.Assert(value != null, "Warning: TextboxText property
    is null!");
    if (value != null)
    {
    EnsureChildControls();
    m_txt.Text = value;
    }
    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
    {
    EnsureChildControls();
    return m_txt.MaxLength;
    }
    set
    {
    EnsureChildControls();
    m_txt.MaxLength = value;
    }
    }

    #endregion

    }
    }
    Christophe Peillet, Jan 10, 2006
    #5
  6. Problem Solved

    I solved the problem by adding the following code to the Designer class.
    Thanks for your help on this.

    /// <summary>
    /// Gets the HTML that is used to represent the control at design
    time.
    /// </summary>
    /// <returns>
    /// The HTML that is used to represent the control at design time.
    /// </returns>
    public override string GetDesignTimeHtml()
    {
    // ToDo: Change type
    SupportTextBox txt = this.Component as SupportTextBox;

    // Create temporary HtmlTextWriter placeholder
    StringBuilder stringBuilder = new StringBuilder();
    StringWriter stringWriter = new StringWriter(stringBuilder);
    HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);

    // Render control
    txt.RenderControl(htmlWriter);

    return stringBuilder.ToString();
    }
    Christophe Peillet, Jan 10, 2006
    #6
  7. RE: Problem Solved

    That's cool Man!

    Yes, for design-time html representation ,we are recommended to make use of
    the GetDesignTimeHtml method of the designer. Glad that you've overcome the
    problem.
    Wish you good luck continually...

    Regards,

    Steven Cheng
    Microsoft Online Support

    Get Secure! www.microsoft.com/security
    (This posting is provided "AS IS", with no warranties, and confers no
    rights.)


    --------------------
    | Thread-Topic: Problem Solved
    | thread-index: AcYV5yv83w0iuM2jRoCrkfkXXcw1NA==
    | X-WBNR-Posting-Host: 193.172.19.20
    | From: =?Utf-8?B?Q2hyaXN0b3BoZSBQZWlsbGV0?=
    <>
    | References: <>
    <>
    <>
    | Subject: Problem Solved
    | Date: Tue, 10 Jan 2006 05:10:04 -0800
    | Lines: 25
    | Message-ID: <>
    | MIME-Version: 1.0
    | Content-Type: text/plain;
    | charset="Utf-8"
    | Content-Transfer-Encoding: 7bit
    | X-Newsreader: Microsoft CDO for Windows 2000
    | Content-Class: urn:content-classes:message
    | Importance: normal
    | Priority: normal
    | X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.0
    | Newsgroups: microsoft.public.dotnet.framework.aspnet.webcontrols
    | NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 10.40.2.250
    | Path: TK2MSFTNGXA02.phx.gbl!TK2MSFTNGXA01.phx.gbl!TK2MSFTNGXA03.phx.gbl
    | Xref: TK2MSFTNGXA02.phx.gbl
    microsoft.public.dotnet.framework.aspnet.webcontrols:32365
    | X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webcontrols
    |
    | I solved the problem by adding the following code to the Designer class.
    | Thanks for your help on this.
    |
    | /// <summary>
    | /// Gets the HTML that is used to represent the control at design
    | time.
    | /// </summary>
    | /// <returns>
    | /// The HTML that is used to represent the control at design time.
    | /// </returns>
    | public override string GetDesignTimeHtml()
    | {
    | // ToDo: Change type
    | SupportTextBox txt = this.Component as SupportTextBox;
    |
    | // Create temporary HtmlTextWriter placeholder
    | StringBuilder stringBuilder = new StringBuilder();
    | StringWriter stringWriter = new StringWriter(stringBuilder);
    | HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
    |
    | // Render control
    | txt.RenderControl(htmlWriter);
    |
    | return stringBuilder.ToString();
    | }
    |
    Steven Cheng[MSFT], Jan 12, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?cGF0cmlja2RyZA==?=

    Client side changes not reflected in page

    =?Utf-8?B?cGF0cmlja2RyZA==?=, Feb 1, 2007, in forum: ASP .Net
    Replies:
    24
    Views:
    1,007
    =?Utf-8?B?cGF0cmlja2RyZA==?=
    Mar 28, 2007
  2. chandru
    Replies:
    1
    Views:
    607
    bruce barker
    Jul 20, 2007
  3. =?Utf-8?B?cGF0cmlja2RyZA==?=

    my.settings edit (after publish) not reflected!

    =?Utf-8?B?cGF0cmlja2RyZA==?=, Sep 6, 2007, in forum: ASP .Net
    Replies:
    1
    Views:
    424
    Juan T. Llibre
    Sep 6, 2007
  4. John Kotuby
    Replies:
    2
    Views:
    3,069
    John Kotuby
    Apr 19, 2008
  5. swalkertdci
    Replies:
    1
    Views:
    138
    swalkertdci
    Aug 23, 2006
Loading...

Share This Page