Thursday, October 14, 2010

How to highlight invalid controls on a postback with asp.net validation controls


Demo:
On Load method, first of anything I validate the page because then only all the validators get their IsValid property set up. Then iterate though the page validator collection (Page.Validators) and because this simple demonstration is only for required field validators, I caste the validator to a RequiredFieldValidator.
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    if (this.IsPostBack)
    {
        this.Validate();
        foreach (object v in this.Validators)
        {
            if (v is RequiredFieldValidator)
            {
                RequiredFieldValidator r = v as RequiredFieldValidator;
                TextBox t = this.FindField(this.Page.Form, r.ControlToValidate) as TextBox;
                if (t != null)
                {
                    if (r.IsValid)
                        t.BackColor = System.Drawing.Color.Green;
                    else
                        t.BackColor = System.Drawing.Color.Red;
                }
 
            }
        }
    }
}
Then the most interesting bit is the The FindField(...) method. You may ask why we can’t use FindControl(...) method. The problem is it works when you work with simple page where you have controls directly in the form it works, but when it comes to complex pages with master pages and content place holders, FindControl(...) didn’t work. So I implemented a recursive method which grills down in the control hierarchy and find the control. I start with this.Page.Form as for sure we know we can’t put form related controls outside the form control. What it all does it find the control in its first level controls (Controls collection) and if it can’t find the given control by its id, it go thorough it’s child control collection and recursively try to find the control. If it finds the control return the found control immediately, if not keep looking. Finally if you still can’t find the control return null. 
private Control FindField(Control source, string id)
{
    Control target = source.FindControl(id);
    if (target != nullreturn target;
    foreach (Control child in source.Controls)
    {
        target = this.FindField(child, id);
        if (target != nullreturn target;
    }
    return null;
}
Put them all together,
Complete Example:
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
    <script runat="server">
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (this.IsPostBack)
            {
                this.Validate();
                foreach (object v in this.Validators)
                {
                    if (v is RequiredFieldValidator)
                    {
                        RequiredFieldValidator r = v as RequiredFieldValidator;
                        TextBox t = this.FindField(this.Page.Form, r.ControlToValidate) as TextBox;
                        if (t != null)
                        {
                            if (r.IsValid)
                                t.BackColor = System.Drawing.Color.Green;
                            else
                                t.BackColor = System.Drawing.Color.Red;
                        }
 
                    }
                }
            }
        }
        private Control FindField(Control source, string id)
        {
            Control target = source.FindControl(id);
            if (target != nullreturn target;
            foreach (Control child in source.Controls)
            {
                target = this.FindField(child, id);
                if (target != nullreturn target;
            }
            return null;
        }
        protected void Save(object sender, EventArgs e)
        {
 
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        Name: <asp:TextBox runat="server" ID="txtName" />
        <asp:RequiredFieldValidator runat="server" ID="rvalName" ControlToValidate="txtName" 
                                    ErrorMessage="Name is required" EnableClientScript="false" /><br />
        Address: <asp:TextBox runat="server" ID="txtAddress" />
        <asp:RequiredFieldValidator runat="server" ID="rvalAddress" ControlToValidate="txtAddress" 
                                    ErrorMessage="Address is required" EnableClientScript="false" /><br />
        Phone: <asp:TextBox runat="server" ID="txtPhone" />
        <asp:RequiredFieldValidator runat="server" ID="rvalPhone" ControlToValidate="txtPhone" 
                                    ErrorMessage="Phone is required" EnableClientScript="false" /><br />
        <hr />
        <asp:Button runat="server" ID="btnSave" OnClick="Save" Text="Save" />
    </form>
</body>
</html>

3 comments:

Ciupaz said...

Hi,
can I use this snippet also in an user control?

Ciupaz said...

Hi,
is it possible to use it also in an user control?

Charith Shyam Gunasekara said...

Yes we can use this inside a control

Azure Storage Account Types

Defferent Types of Blobs Block blobs store text and binary data. Block blobs are made up of blocks of data that can be managed individually...