|
||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionContinuing the trend introduced by my previous article Numeric Edit Box, I'm going to use the same technique of validating the text string, reducing one char at a time from the end until I'll get a valid number, this time - for Web Pages. And, because ChallengesA big challenge is to make the validation work on different controls containing a string text = "";
Control ctrl = this.Page.FindControl(ControlToValidate);
//if (ctrl==null) throw new Exception("No ControlToValidate.");
Type t = ctrl.GetType();
System.Reflection.FieldInfo fi = t.GetField("Text");
if (fi!=null) {
text = (string)(fi.GetValue(ctrl));
} else {
System.Reflection.PropertyInfo pi = t.GetProperty("Text");
if (pi!=null)
text = (string)(pi.GetValue(ctrl, new object [] {}));
else
throw new Exception("ControlToValidate " +
"should have a Text field or property.");
}
The above code makes sure that the protected override bool EvaluateIsValid() {
try {
// Get control to validate
// Validate core
} catch (Exception e) {
Text = e.Message+" "+e.InnerException;
return false;
}
}
So, whatever error comes directly (with Express YourselfHTML Edit Controls do not have the Of course, the easiest way is to fragment the text from the input control using a separator, something like: // Get control to validate
string s = text;
int l = s.Length;
// Validate core
if (s.Length!=l) {
Text = "<i>"+ErrorMessage+":</i> " + s +
"->"+text.Substring(s.Length,l-s.Length);
return false;
} else return true;
Tip: italic makes the error message more visible. The result looks ... not very well:
Then, using the control from my previous article "Simple WebControl to Display Unicode Tables", I got some fancy characters to use as separator:
Text = "<i>"+ErrorMessage+":</i> "+ s +
"\u25ba"+text.Substring(s.Length,l-s.Length);
Too loaded... besides, for other cultures or implementations, these chars might look different - I did not investigate and this is a risk. Other variations: strike out (123 And then, it hits me: HTML Tables are very versatileWhat a ... HTML tables have to do with validation controls? Well, I could use an HTML table for the text of the message. This way, I can color the background of the error part of the entry: Text = "<TABLE border=\"0\" cellpaddingleft=\"2\" " +
"cellpaddingright=\"1\" cellspacing=\"0\">"
+"<tr><td><font color=\""
+System.Drawing.ColorTranslator.ToHtml(ForeColor)+"\"><i>"
+ErrorMessage+": </i><b>"+s+"</font></b></td>"
+"<td bgcolor=\""+System.Drawing.ColorTranslator.ToHtml(ForeColor)
+"\"><font color=\""
+System.Drawing.ColorTranslator.ToHtml(BackColor)+"\"><b>"
+text.Substring(s.Length,l-s.Length)+
"</b></font></td></tr></TABLE>";
With a bit of attention to details -
Validation CoreLike in the previous article, the validation starts with the full entry string // Get Control to validate
string s = text;
int l = s.Length;
while (s.Length>0)
try {
Value = (ToValidate==NumValidate.Integer)
? int.Parse(s, NumStyles)
: double.Parse(s, NumStyles);
break;
} catch {
s = s.Substring(0,s.Length-1);
}
if (s.Length!=l) {
Text = // ...
return false;
} else return true;
//...
}
private double _value;
/// <summary>
/// The numeric Value of the Validated control
/// </summary>
[Category("Appearance"),
DefaultValue(0),
Description("The numeric Value of the Validated control")]
public virtual double Value {
get { return _value; }
set { _value = value; }
}
private NumValidate toValidate = NumValidate.Integer;
/// <summary>
/// ToValidate an integer or a double value
/// </summary>
[Category("Appearance"),
DefaultValue(NumValidate.Integer),
Description("ToValidate an integer or a double value")]
public NumValidate ToValidate {
get { return toValidate; }
set { toValidate = value; }
}
private NumberStyles numStyles=
NumberStyles.Number | NumberStyles.AllowExponent;
/// <summary>
/// Customize the numeric validation number style.
/// </summary>
[Category("Appearance"),
DefaultValue(NumberStyles.Number | NumberStyles.AllowExponent),
Description("Customize the numeric validation number style.")]
public NumberStyles NumStyles {
get { return numStyles; }
set { numStyles = value; }
}
public enum NumValidate {
Integer,
Double
}
External Validation
public class ValidateEventArgs : EventArgs {
public ValidateEventArgs():this("") {
}
public ValidateEventArgs(string text) {
_Validated=false;
_Value=0;
_Text=text;
}
private bool _Validated;
public bool Validated {
get { return _Validated; }
set { _Validated = value; }
}
private string _Text;
public string Text {
get { return _Text; }
set { _Text = value; }
}
private Double _Value;
public Double Value {
get { return _Value; }
set { _Value = value; }
}
}
It inherits from the basic Now, I can use this event argument structure in a new event declared in the main class: public delegate void ValidatingEventHandler(object sender,
ValidateEventArgs e);
public event ValidatingEventHandler Validating;
//...
// Get Control to Validate
string s = text;
int l = s.Length;
if (Validating!=null) {
ValidateEventArgs e = new ValidateEventArgs(s);
Validating(this,e);
if (e.Validated) {
Value = e.Value;
return true;
}
while //...
While that was the approach from the first article, this code can improve in two ways: Separate External Validator HandlersTo use this event, we usually go on the main form, click the validator WebControl, go in Properties panel, in the Events tab, and double-click on the private void NumEditValidator1_Validating(object sender,
TH.WebControls.ValidateEventArgs e) {
if (e.Validated) return;
else if (e.Text=="Pi") {
e.Value=Math.PI;
e.Validated=true;
}
}
Here, I've validated just the named constant foreach (ValidatingEventHandler validating in Validating.GetInvocationList()) {
validating(this,e);
if (e.Validated) {
Value = e.Value;
return true;
}
We still need a little trick for being able to add multiple handlers from Visual Studio: go in the main form's code behind and open the region Web Form Designer generated code. In the method /// <SUMMARY>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </SUMMARY>
private void InitializeComponent() {
This translates in whatever you add here may disappear sooner or later! However, deleting the line won't make Visual Studio to put it back; instead, the corresponding handler disappears from the Properties box. This completes the idea in the following manner: cut the line and paste it in the #region Web Form Designer generated code
override protected void OnInit(EventArgs e) {
InitializeComponent();
this.NumEditValidator1.Validating += new
TH.WebControls.NumEditValidator.ValidatingEventHandler(this.ValidatingPi);
this.NumEditValidator1.Validating += new
TH.WebControls.NumEditValidator.ValidatingEventHandler(this.ValidatingE);
base.OnInit(e);
}
private void InitializeComponent() {
//...
#endregion
private void ValidatingPi(object sender, TH.WebControls.ValidateEventArgs e) {
if (e.Validated) return;
else if (e.Text=="Pi") {
e.Value=Math.PI;
e.Validated=true;
}
}
private void ValidatingE(object sender, TH.WebControls.ValidateEventArgs e) {
if (e.Validated) return;
else if (e.Text=="E") {
e.Value=Math.E;
e.Validated=true;
}
}
Guess what: it works! Feedback from External Validator HandlersNow, let's type instead of
And this is not nice: without another hint (help, use manual, technical support, hot line, topic forum, a little voice etc.) one can never find that the control supports the constant ValidateEventArgs e = new ValidateEventArgs(s);
while (s.Length>0)
try {
if (Validating!=null) {
e.Text = s;
foreach (ValidatingEventHandler validating
in Validating.GetInvocationList()) {
validating(this,e);
if (e.Validated) {
Value = e.Value;
break;
}
}
}
if (!e.Validated) {
Value = (ToValidate==NumValidate.Integer)
? int.Parse(s, NumStyles)
: double.Parse(s, NumStyles);
}
break;
} catch {
s = s.Substring(0,s.Length-1);
}//...
That's all folks! Now, let's draw some - ConclusionsProgramming is fun, and by the time the project approached the final stage, I let it go, but not without some common sense: sometimes the sources of inspiration are so narrow that a good forum is the last hope before wishing that a little voice told you what to do (no - I don't hear some!). I've tried here to produce a control for those in need for help, hints, or support as little as possible. You tell me if I've succeeded! In this exercise, I've discovered the Microsoft way to do validation with separate controls instead of those used for data entry. A round trip to the server for validation is not too expensive when the validation for all edit-controls in a page can happen in just one PostBack. The I hope you've enjoyed this project as much as I did!
|
|||||||||||||||||||||||||||||||||||||||||||||||