|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
ValidationControl evaluationfunction ASP.NET 2.0I'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 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. Show quoteHide quote "jeremy.brews***@akqa.com" wrote: > 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 > > 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 JimOx wrote: Show quoteHide quote > 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. > > "jeremy.brews***@akqa.com" wrote: > > > 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 > > > > 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 <jeremy.brews***@akqa.com> ha scritto nel messaggio Show quoteHide quote news:1151058013.109033.231650@m73g2000cwd.googlegroups.com... > 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 > > > JimOx wrote: >> 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. >> >> "jeremy.brews***@akqa.com" wrote: >> >> > 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 >> > >> > > 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: Show quoteHide quote > 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 > <jeremy.brews***@akqa.com> ha scritto nel messaggio > news:1151058013.109033.231650@m73g2000cwd.googlegroups.com... > > 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 > > > > > > JimOx wrote: > >> 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. > >> > >> "jeremy.brews***@akqa.com" wrote: > >> > >> > 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 > >> > > >> > > > 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. Show quoteHide quote "jeremy.brews***@akqa.com" wrote: > 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 > > <jeremy.brews***@akqa.com> ha scritto nel messaggio > > news:1151058013.109033.231650@m73g2000cwd.googlegroups.com... > > > 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) > > > { 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 Show quoteHide quote "JimOx" <Ji***@discussions.microsoft.com> ha scritto nel messaggio news:B3AD086D-DE1E-4DC2-97F8-6B37534C30B3@microsoft.com... > 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. > > "jeremy.brews***@akqa.com" wrote: > >> 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 >> > <jeremy.brews***@akqa.com> ha scritto nel messaggio >> > news:1151058013.109033.231650@m73g2000cwd.googlegroups.com... >> > > 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) >> > > { 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 Zifiglio wrote: Show quoteHide quote > 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" <Ji***@discussions.microsoft.com> ha scritto nel messaggio > news:B3AD086D-DE1E-4DC2-97F8-6B37534C30B3@microsoft.com... > > 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. > > > > "jeremy.brews***@akqa.com" wrote: > > > >> 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 > >> > <jeremy.brews***@akqa.com> ha scritto nel messaggio > >> > news:1151058013.109033.231650@m73g2000cwd.googlegroups.com... > >> > > 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) > >> > > { Hi guys, had a similar problem.
I tried to override the AddAttributesToRender and RegisterExpandoAttribute as mentioned but when I use my control on a page, I'm getting a "an entry with the same key already exists exception" I only get the error when overriding the AddAttributesToRender. I don't call the base method and I'm inheriting BaseValidator. Any thoughts? Thanks in advance *** Sent via Developersdex http://www.developersdex.com ***
Gridview extra header row with command button and paging
Formview Question validation message only show in val summary when ShowSummary=true when no js to execute on client Client ID of User Control in Page templates Event from one WebControl triggering an event in another Web control XML Dropdownlist- Custom DataTextField Anyway to enable a ToolTip for each ListItem Is it possible to get only the "Selected" text out of a TextBox radiobuttons - no list Display text with <newline> characters... |
|||||||||||||||||||||||