ValidationControl evaluationfunction ASP.NET 2.0

J

jeremy.brewster

Hello

I'm trying to work out how to call a custom evaluation function for a
Validation Control (via the "evaluationfunction" attribute) to change
the visual style of the div hosting the input control if validation
fails. We have this working as a fallback on the server-side (if
client-side script is turned off) but want/need this working on the
client-side also.

I am working on a website which included this behaviour in .NET 1.1 but
I am having trouble getting it to work with .NET 2.0.

I've tried setting the evaluation function using:
this.validator.Attributes["evaluationfunction"] in the server-side
helper class that includes an instance of the validator but this seems
to be ignored by the browser and does not result in the client-side
function being called. When I use:
this.validator.Page.ClientScript.RegisterExpandoAttribute("...") I
receive an error stating "System.ArgumentException: An entry with the
same key already exists."

Indeed when we use the DOM Inspector from Firefox on the page we can
see that the evaluationfunction attribute for the validator already has
the following out-of-the-box client-script defined:

function RegularExpressionValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
if (ValidatorTrim(value).length == 0) {
return true;
}
var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
}

So I'm thinking that what I need is the ability to change the
evaluationfunction value to my own custom code. I'm having no luck
whatsoever with this.

Does anybody have any ideas on how to solve this. Thanks in advance.

Jez
 
J

JimOx

You could write a custom validator that implements the BaseValidator. Then if
you override AddAttributesToRender use
Page.ClientScript.RegisterExpandoAttribute(ClientID, "evaluationfunction",
"ClientSideFunctionToCall", false); and it should work.
 
J

jeremy.brewster

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)
{
HtmlControl foundHtmlControl = (HtmlControl) this.foundControl;
foundHtmlControl.Attributes.Add("class", this.changeCssClass);
}
}
}
return isValid;
}

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

When I compile and run this code, we receive a
"System.ArgumentException: An entry with the same key already exists."
highlighting the AddAttributesToRender method in the
StyleChangingRequiredFieldValidator class.

If I don't use the Page.ClientScript.RegisterExpandoAttribute method to
write the evaluationfunction attribute (instead using:
validator.Attributes["evaluationfunction"] = ...) then the value
written is effectively ignored by the web page (although written to the
page html as observed in notepad). When I say that it is ignored by
the web page, I know this from running the Firefox DOM Inspector which
states that the ASP.NET out-of-the-box required field validator
function is being used.

function RequiredFieldValidatorEvaluateIsValid(val) {
return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) !=
ValidatorTrim(val.initialvalue));
}

So I'm again stuck with not being able to replace the out-of-the-box
javascript evaluationfunction value with my own custom implementation
in which I want to dynamically change the style of the div elements
hosting the input control should validation fail.

Does anybody have any ideas?

Thanks

Jez

You could write a custom validator that implements the BaseValidator. Then if
you override AddAttributesToRender use
Page.ClientScript.RegisterExpandoAttribute(ClientID, "evaluationfunction",
"ClientSideFunctionToCall", false); and it should work.

Hello

I'm trying to work out how to call a custom evaluation function for a
Validation Control (via the "evaluationfunction" attribute) to change
the visual style of the div hosting the input control if validation
fails. We have this working as a fallback on the server-side (if
client-side script is turned off) but want/need this working on the
client-side also.

I am working on a website which included this behaviour in .NET 1.1 but
I am having trouble getting it to work with .NET 2.0.

I've tried setting the evaluation function using:
this.validator.Attributes["evaluationfunction"] in the server-side
helper class that includes an instance of the validator but this seems
to be ignored by the browser and does not result in the client-side
function being called. When I use:
this.validator.Page.ClientScript.RegisterExpandoAttribute("...") I
receive an error stating "System.ArgumentException: An entry with the
same key already exists."

Indeed when we use the DOM Inspector from Firefox on the page we can
see that the evaluationfunction attribute for the validator already has
the following out-of-the-box client-script defined:

function RegularExpressionValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
if (ValidatorTrim(value).length == 0) {
return true;
}
var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
}

So I'm thinking that what I need is the ability to change the
evaluationfunction value to my own custom code. I'm having no luck
whatsoever with this.

Does anybody have any ideas on how to solve this. Thanks in advance.

Jez
 
A

Alessandro Zifiglio

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
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)
{
HtmlControl foundHtmlControl = (HtmlControl) this.foundControl;
foundHtmlControl.Attributes.Add("class", this.changeCssClass);
}
}
}
return isValid;
}

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

When I compile and run this code, we receive a
"System.ArgumentException: An entry with the same key already exists."
highlighting the AddAttributesToRender method in the
StyleChangingRequiredFieldValidator class.

If I don't use the Page.ClientScript.RegisterExpandoAttribute method to
write the evaluationfunction attribute (instead using:
validator.Attributes["evaluationfunction"] = ...) then the value
written is effectively ignored by the web page (although written to the
page html as observed in notepad). When I say that it is ignored by
the web page, I know this from running the Firefox DOM Inspector which
states that the ASP.NET out-of-the-box required field validator
function is being used.

function RequiredFieldValidatorEvaluateIsValid(val) {
return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) !=
ValidatorTrim(val.initialvalue));
}

So I'm again stuck with not being able to replace the out-of-the-box
javascript evaluationfunction value with my own custom implementation
in which I want to dynamically change the style of the div elements
hosting the input control should validation fail.

Does anybody have any ideas?

Thanks

Jez

You could write a custom validator that implements the BaseValidator.
Then if
you override AddAttributesToRender use
Page.ClientScript.RegisterExpandoAttribute(ClientID,
"evaluationfunction",
"ClientSideFunctionToCall", false); and it should work.

Hello

I'm trying to work out how to call a custom evaluation function for a
Validation Control (via the "evaluationfunction" attribute) to change
the visual style of the div hosting the input control if validation
fails. We have this working as a fallback on the server-side (if
client-side script is turned off) but want/need this working on the
client-side also.

I am working on a website which included this behaviour in .NET 1.1 but
I am having trouble getting it to work with .NET 2.0.

I've tried setting the evaluation function using:
this.validator.Attributes["evaluationfunction"] in the server-side
helper class that includes an instance of the validator but this seems
to be ignored by the browser and does not result in the client-side
function being called. When I use:
this.validator.Page.ClientScript.RegisterExpandoAttribute("...") I
receive an error stating "System.ArgumentException: An entry with the
same key already exists."

Indeed when we use the DOM Inspector from Firefox on the page we can
see that the evaluationfunction attribute for the validator already has
the following out-of-the-box client-script defined:

function RegularExpressionValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
if (ValidatorTrim(value).length == 0) {
return true;
}
var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
}

So I'm thinking that what I need is the ability to change the
evaluationfunction value to my own custom code. I'm having no luck
whatsoever with this.

Does anybody have any ideas on how to solve this. Thanks in advance.

Jez
 
J

jeremy.brewster

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 said:
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
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)
{
HtmlControl foundHtmlControl = (HtmlControl) this.foundControl;
foundHtmlControl.Attributes.Add("class", this.changeCssClass);
}
}
}
return isValid;
}

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

When I compile and run this code, we receive a
"System.ArgumentException: An entry with the same key already exists."
highlighting the AddAttributesToRender method in the
StyleChangingRequiredFieldValidator class.

If I don't use the Page.ClientScript.RegisterExpandoAttribute method to
write the evaluationfunction attribute (instead using:
validator.Attributes["evaluationfunction"] = ...) then the value
written is effectively ignored by the web page (although written to the
page html as observed in notepad). When I say that it is ignored by
the web page, I know this from running the Firefox DOM Inspector which
states that the ASP.NET out-of-the-box required field validator
function is being used.

function RequiredFieldValidatorEvaluateIsValid(val) {
return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) !=
ValidatorTrim(val.initialvalue));
}

So I'm again stuck with not being able to replace the out-of-the-box
javascript evaluationfunction value with my own custom implementation
in which I want to dynamically change the style of the div elements
hosting the input control should validation fail.

Does anybody have any ideas?

Thanks

Jez

You could write a custom validator that implements the BaseValidator.
Then if
you override AddAttributesToRender use
Page.ClientScript.RegisterExpandoAttribute(ClientID,
"evaluationfunction",
"ClientSideFunctionToCall", false); and it should work.

:

Hello

I'm trying to work out how to call a custom evaluation function for a
Validation Control (via the "evaluationfunction" attribute) to change
the visual style of the div hosting the input control if validation
fails. We have this working as a fallback on the server-side (if
client-side script is turned off) but want/need this working on the
client-side also.

I am working on a website which included this behaviour in .NET 1.1 but
I am having trouble getting it to work with .NET 2.0.

I've tried setting the evaluation function using:
this.validator.Attributes["evaluationfunction"] in the server-side
helper class that includes an instance of the validator but this seems
to be ignored by the browser and does not result in the client-side
function being called. When I use:
this.validator.Page.ClientScript.RegisterExpandoAttribute("...") I
receive an error stating "System.ArgumentException: An entry with the
same key already exists."

Indeed when we use the DOM Inspector from Firefox on the page we can
see that the evaluationfunction attribute for the validator already has
the following out-of-the-box client-script defined:

function RegularExpressionValidatorEvaluateIsValid(val) {
var value = ValidatorGetValue(val.controltovalidate);
if (ValidatorTrim(value).length == 0) {
return true;
}
var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
}

So I'm thinking that what I need is the ability to change the
evaluationfunction value to my own custom code. I'm having no luck
whatsoever with this.

Does anybody have any ideas on how to solve this. Thanks in advance.

Jez
 
J

JimOx

Jeremy,

I believe that to do this you can go one of two ways. Either don't call the
base.AddAttributesToRender in your overriding method. This will require you
to have to manually register all of the attributes that the base class would
have registered that you need. The other option is to inherit from
BaseValidator instead of RequiredFieldValidator. This is because
BaseValidator does not register the
"evaluationfunction" attribute but RequiredFieldValidator does and as far as
I know once an ExpandoAttribute is registered there is no way to change it's
value or remove the original.

As a side note you will need to use
Page.ClientScript.RegisterExpandoAttribute to write the attribute instead of
writer.AddAttribute. This is because if you use writer.AddAttribute it will
work in IE but not FireFox. However
Page.ClientScript.RegisterExpandoAttribute will work in both.

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 said:
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
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)
{
 
A

Alessandro Zifiglio

hi Jeremy,
so its just as Jim clearly stated in the previous post. In your place, i
wont inherit the RequiredFieldValidator control. But write my own custom
validator. The requiredFieldValidator control does not do much anyway, and
there is minimum code for it. All the meat and postatoes of this controls
code is just registering in the AddAttributesToRender method, only that
un-needed expandoattribute that you want to exclude from your custom
implementatoin, defining your own. Since you want to write a customized
implementation, deriving from baseValidator is the way to go. Otherwise you
have to deal with the obstacles you are dealing with now and also for
nothing.

Good luck,
Alessandro Zifiglio

JimOx said:
Jeremy,

I believe that to do this you can go one of two ways. Either don't call
the
base.AddAttributesToRender in your overriding method. This will require
you
to have to manually register all of the attributes that the base class
would
have registered that you need. The other option is to inherit from
BaseValidator instead of RequiredFieldValidator. This is because
BaseValidator does not register the
"evaluationfunction" attribute but RequiredFieldValidator does and as far
as
I know once an ExpandoAttribute is registered there is no way to change
it's
value or remove the original.

As a side note you will need to use
Page.ClientScript.RegisterExpandoAttribute to write the attribute instead
of
writer.AddAttribute. This is because if you use writer.AddAttribute it
will
work in IE but not FireFox. However
Page.ClientScript.RegisterExpandoAttribute will work in both.

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 said:
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)
{
 
J

jeremy.brewster

Hi Jim, Alessandro

Thanks for your advice on this issue. As you have both suggested I
have derived my required field validator directly from BaseValidator
and this is now working great.

I also had to create a regular expression validator and a compare
validator to derive from BaseValidator and these are also now working
great.

I had a few issues creating a "custom" custom validator to derive from
BaseValidator rather than the CustomValidator class with respect to
wiring up the server validation events for each type of custom
validator but this is also now working.

Thanks again for your advice.

Jez

Alessandro said:
hi Jeremy,
so its just as Jim clearly stated in the previous post. In your place, i
wont inherit the RequiredFieldValidator control. But write my own custom
validator. The requiredFieldValidator control does not do much anyway, and
there is minimum code for it. All the meat and postatoes of this controls
code is just registering in the AddAttributesToRender method, only that
un-needed expandoattribute that you want to exclude from your custom
implementatoin, defining your own. Since you want to write a customized
implementation, deriving from baseValidator is the way to go. Otherwise you
have to deal with the obstacles you are dealing with now and also for
nothing.

Good luck,
Alessandro Zifiglio

JimOx said:
Jeremy,

I believe that to do this you can go one of two ways. Either don't call
the
base.AddAttributesToRender in your overriding method. This will require
you
to have to manually register all of the attributes that the base class
would
have registered that you need. The other option is to inherit from
BaseValidator instead of RequiredFieldValidator. This is because
BaseValidator does not register the
"evaluationfunction" attribute but RequiredFieldValidator does and as far
as
I know once an ExpandoAttribute is registered there is no way to change
it's
value or remove the original.

As a side note you will need to use
Page.ClientScript.RegisterExpandoAttribute to write the attribute instead
of
writer.AddAttribute. This is because if you use writer.AddAttribute it
will
work in IE but not FireFox. However
Page.ClientScript.RegisterExpandoAttribute will work in both.

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)
{
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top