Hi Alessando
If I don't call the validator base.AddAttributesToRender then no aspect
of the validator gets written to the page.
As you say, I am overriding the AddAttributesToRender method in my
custom validators and they do indeed call the StyleChangingHelper
instance variable's method of the same name.
MSDN states "Notes to Inheritors When overriding the
AddAttributesToRender method, be sure to call the corresponding method
in the base class. Otherwise, the attributes contained in the base
class will not be rendered."
Or are you suggesting that my override that does not call the base
implementation needs to do more than it is doing at the minute?
The StyleChangingRequiredFieldValidator has the following OnPreRender
and AddAttributesToRender methods:
/// <summary>
/// Raises the PreRender event.
/// </summary>
/// <param name="e">An EventArgs object that contains the event
data.</param>
protected override void OnPreRender(System.EventArgs e)
{
this.helper.OnPreRender(e);
base.OnPreRender(e);
}
/// <summary>
/// Adds HTML attributes and styles that need to be rendered to the
specified System.Web.UI.HtmlTextWriter.
/// </summary>
/// <param name="writer">A System.Web.UI.HtmlTextWriter that represents
the output stream to render HTML content on the client.</param>
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
this.helper.AddAttributesToRender(writer, this.RenderUplevel);
}
The StyleChangingHelper has the following custom methods of the same
names:
/// <summary>
/// Should be called by the base validator upon raising the PreRender
event.
/// </summary>
/// <param name="e">An EventArgs object that contains the event
data.</param>
public void OnPreRender(System.EventArgs e)
{
if (this.validator.EnableClientScript)
{
// this.validator.Attributes["evaluationfunction"] =
this.validator.GetType().Name + evaluationFunctionSuffix;
this.validator.Page.ClientScript.RegisterExpandoAttribute(validator.ClientID,
"evaluationfunction", this.validator.GetType().Name +
evaluationFunctionSuffix);
}
}
/// <summary>
/// Adds HTML attributes and styles that need to be rendered to the
specified System.Web.UI.HtmlTextWriter.
/// </summary>
/// <param name="writer">A System.Web.UI.HtmlTextWriter that represents
the output stream to render HTML content on the client.</param>
/// <param name="renderUpLevel">Indicates whether the client's browser
supports uplevel rendering.</param>
public void AddAttributesToRender(HtmlTextWriter writer, bool
renderUpLevel)
{
if (renderUpLevel)
{
string renderedControlID;
renderedControlID = DeriveId('_');
writer.AddAttribute("controltochange", renderedControlID);
writer.AddAttribute("changecssclass", ChangeCssClass);
writer.AddAttribute("originalcssclass", this.originalCssClass);
}
}
Alessandro Zifiglio wrote:
hi Jeremy, in your override of AddAttributesToRender, do not call
base.AddAttributesToRender. Instead what you need to do is override
this
method as you are currently doing and add apply your customized
attributes
to it, which is probably being done via the method call to your helper
class.
Regards,
Alessandro Zifiglio
<
[email protected]> ha scritto nel messaggio
Hi Jim
Thanks for the reply. This is something we are already doing. We
have
subclassed each validator for which we want to create a customised
behaviour. So we have a class with the following definition:
public class StyleChangingRequiredFieldValidator :
RequiredFieldValidator
{
private StyleChangingHelper helper;
/// <summary>
/// Default constructor.
/// </summary>
public StyleChangingRequiredFieldValidator()
{
this.helper = new StyleChangingHelper(this);
}
/// <summary>
/// The control whose style should be changed when validation results
in an invalid state.
/// </summary>
public string ControlToChange
{
get
{
return this.helper.ControlToChange;
}
set
{
this.helper.ControlToChange = value;
}
}
/// <summary>
/// The CSS class to use when changing the style of the targeted
control.
/// </summary>
public string ChangeCssClass
{
get
{
return this.helper.ChangeCssClass;
}
set
{
this.helper.ChangeCssClass = value;
}
}
/// <summary>
/// Raises the Init event.
/// </summary>
/// <param name="e">An EventArgs object that contains the event
data.</param>
protected override void OnInit(System.EventArgs e)
{
base.OnInit(e);
this.helper.OnInit(e);
}
/// <summary>
/// Determines whether the value in the input control is valid.
/// </summary>
/// <returns><c>true</c> if the value in the input control is valid;
otherwise, <c>false</c>.</returns>
protected override bool EvaluateIsValid()
{
bool isValid = base.EvaluateIsValid();
return this.helper.EvaluateIsValid(isValid);
}
/// <summary>
/// Raises the PreRender event.
/// </summary>
/// <param name="e">An EventArgs object that contains the event
data.</param>
protected override void OnPreRender(System.EventArgs e)
{
this.helper.OnPreRender(e);
base.OnPreRender(e);
}
/// <summary>
/// Adds HTML attributes and styles that need to be rendered to the
specified System.Web.UI.HtmlTextWriter.
/// </summary>
/// <param name="writer">A System.Web.UI.HtmlTextWriter that
represents the output stream to render HTML content on the
client.</param>
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
this.helper.AddAttributesToRender(writer, this.RenderUplevel);
}
}
We have created a StyleChangingHelper class, an instance of which is
instantiated by each Validator derived subclass, and objects based on
this class handle the writing of the attributes.
/// <summary>
/// Provides functionality for style changing validation controls.
/// </summary>
public class StyleChangingHelper
{
private BaseValidator validator;
private string controlToChange;
private string changeCssClass;
private object foundControl;
private string originalCssClass;
private const string evaluationFunctionSuffix = "_Verify";
/// <summary>
/// Constructor which initialises the helper with a validator
instance.
/// </summary>
/// <param name="validator">The validator that this helper will be
helping.</param>
public StyleChangingHelper(BaseValidator validator)
{
this.validator = validator;
}
/// <summary>
/// The control whose style should be changed when validation results
in an invalid state.
/// </summary>
public string ControlToChange
{
get
{
return this.controlToChange;
}
set
{
this.controlToChange = value;
}
}
/// <summary>
/// The CSS class to use when changing the style of the targeted
control.
/// </summary>
public string ChangeCssClass
{
get
{
return this.changeCssClass;
}
set
{
this.changeCssClass = value;
}
}
/// <summary>
/// Should be called by the base validator upon raising the Init
event.
/// </summary>
/// <param name="e">An EventArgs object that contains the event
data.</param>
public void OnInit(System.EventArgs e)
{
string controlID = DeriveId('$');
this.foundControl = this.validator.Page.FindControl(controlID);
if (this.foundControl != null)
{
if (this.foundControl is WebControl)
{
WebControl foundWebControl = (WebControl) this.foundControl;
this.originalCssClass = foundWebControl.CssClass;
}
else if (foundControl is HtmlControl)
{
HtmlControl foundHtmlControl = (HtmlControl) this.foundControl;
this.originalCssClass = foundHtmlControl.Attributes["class"];
}
}
}
/// <summary>
/// Determines whether the value in the input control is valid.
/// </summary>
/// <param name="isValid">Indicates whether the calling validator
considers the input control valid.</param>
public bool EvaluateIsValid(bool isValid)
{
if (!isValid)
{
if (this.foundControl != null)
{
if (this.foundControl is WebControl)
{
WebControl foundWebControl = (WebControl) this.foundControl;
foundWebControl.CssClass = this.changeCssClass;
}
else if (foundControl is HtmlControl)
{