Changed property values not reflected in DesignMode

  • Thread starter Christophe Peillet
  • Start date
C

Christophe Peillet

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
}
}
 
C

Christophe Peillet

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

}
 
S

Steven Cheng[MSFT]

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?=
<[email protected]>
| References: <[email protected]>
| Subject: Designer Code for this control
| Date: Mon, 9 Jan 2006 01:13:01 -0800
| Lines: 505
| Message-ID: <[email protected]>
| 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
|
| }
|
|
 
C

Christophe Peillet

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

}
}
 
C

Christophe Peillet

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

}
}
 
C

Christophe Peillet

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();
}
 
S

Steven Cheng[MSFT]

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?=
<[email protected]>
| References: <[email protected]>
<[email protected]>
<[email protected]>
| Subject: Problem Solved
| Date: Tue, 10 Jan 2006 05:10:04 -0800
| Lines: 25
| Message-ID: <[email protected]>
| 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();
| }
|
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top