Tuesday, August 16, 2011

Using Radio Button in GridView with Validation


Using Radio Button in GridView with Validation

A developer is asking how to select one radio button at a time if the radio button is inside the GridView.  As you may know setting the group name attribute of radio button will not work if the radio button is located within a Data Representation control like GridView. This because the radio button inside the gridview bahaves differentely. Since a gridview is rendered as table element , at run time it will assign different "name" to each radio button. Hence you are able to select multiple rows.
In this post I'm going to demonstrate how select one radio button at a time in gridview and add a simple validation on it. To get started let's go ahead and fire up visual studio and the create a new web application / website project. Add a WebForm and then add gridview. The mark up would look something like this:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" >
        <Columns>
            <asp:TemplateField>
                <ItemTemplate>
                   <asp:RadioButton ID="rb" runat="server" />
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="RowNumber" HeaderText="Row Number" />
            <asp:BoundField DataField="Col1" HeaderText="First Column" />
            <asp:BoundField DataField="Col2" HeaderText="Second Column" />
        </Columns>
</asp:GridView>

Noticed that I've added a templatefield column so that we can add the radio button there. Also I have set up some BoundField columns and set the DataFields as RowNumber, Col1 and Col2. These columns are just dummy columns and i used it for the simplicity of this example. Now where these columns came from? These columns are created by hand at the code behind file of the ASPX. Here's the code below:

private DataTable FillData() {

            DataTable dt = new DataTable();
            DataRow dr = null;

            //Create DataTable columns
            dt.Columns.Add(new DataColumn("RowNumber", typeof(string)));
            dt.Columns.Add(new DataColumn("Col1", typeof(string)));
            dt.Columns.Add(new DataColumn("Col2", typeof(string)));

            //Create Row for each columns
            dr = dt.NewRow();
            dr["RowNumber"] = 1;
            dr["Col1"] = "A";
            dr["Col2"] = "B";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["RowNumber"] = 2;
            dr["Col1"] = "AA";
            dr["Col2"] = "BB";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["RowNumber"] = 3;
            dr["Col1"] = "A";
            dr["Col2"] = "B";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["RowNumber"] = 4;
            dr["Col1"] = "A";
            dr["Col2"] = "B";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["RowNumber"] = 5;
            dr["Col1"] = "A";
            dr["Col2"] = "B";
            dt.Rows.Add(dr);

            return dt;
}

And here's the code for binding the GridView with the dummy data above.
protected void Page_Load(object sender, EventArgs e) {
            if (!IsPostBack) {
                GridView1.DataSource = FillData();
                GridView1.DataBind();
            }
}

Okay we have now a GridView data with a radio button on each row. Now lets go ahead and switch back to ASPX mark up. In this example I'm going to use a JavaScript for validating the radio button to select one radio button at a time. Here's the javascript code below:
function CheckOtherIsCheckedByGVID(rb) {
        var isChecked = rb.checked;
        var row = rb.parentNode.parentNode;
        if (isChecked) {
            row.style.backgroundColor = '#B6C4DE';
            row.style.color = 'black';
        }
        var currentRdbID = rb.id;
        parent = document.getElementById("<%= GridView1.ClientID %>");
        var items = parent.getElementsByTagName('input');

        for (i = 0; i < items.length; i++) {
            if (items[i].id != currentRdbID && items[i].type == "radio") {
                if (items[i].checked) {
                    items[i].checked = false;
                    items[i].parentNode.parentNode.style.backgroundColor = 'white';
                    items[i].parentNode.parentNode.style.color = '#696969';
                }
            }
        }
}

The function above sets the row of the current selected radio button's style to determine that the row is selected and then loops through the radio buttons in the gridview and then de-select the previous selected radio button and set the row style back to its default. You can then call the javascript function above at onlick event of radio button like below:

<asp:RadioButton ID="rb" runat="server" onclick="javascript:CheckOtherIsCheckedByGVID(this);" />

Here's the output below:
On Load:
After Selecting a Radio Button:
As you have noticed, on initial load there's no default selected radio in the GridView. Now let's add a simple validation for that. We will basically display an error message if a user clicks a button that triggers a postback without selecting  a radio button in the GridView. Here's the javascript for the validation:

function ValidateRadioButton(sender, args) {
        var gv = document.getElementById("<%= GridView1.ClientID %>");
        var items = gv.getElementsByTagName('input');
        for (var i = 0; i < items.length ; i++) {
            if (items[i].type == "radio") {
                if (items[i].checked) {
                    args.IsValid = true;
                    return;
                }
                else {
                    args.IsValid = false;
                }
            }
        }
}

The function above loops through the rows in gridview and find all the radio buttons within it. It will then check each radio button checked property. If a radio is checked then set IsValid to true else set it to false.  The reason why I'm using IsValid is because I'm using the ASP validator control for validation. Now add the following mark up below under the GridView declaration:

<br />
    <asp:Label ID="lblMessage" runat="server" />
    <br />
    <asp:Button ID="btn" runat="server" Text="POST" onclick="btn_Click" ValidationGroup="GroupA" />
    <asp:CustomValidator ID="CustomValidator1" runat="server" ErrorMessage="Please select row in the grid." ClientValidationFunction="ValidateRadioButton" ValidationGroup="GroupA" style="display:none"></asp:CustomValidator>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ValidationGroup="GroupA" HeaderText="Error List:" DisplayMode="BulletList" ForeColor="Red" />

And then at Button Click event add this simple code below just to test if  the validation works:

protected void btn_Click(object sender, EventArgs e) {
            lblMessage.Text = "Postback at: " + DateTime.Now.ToString("hh:mm:ss tt");
}

Here's the output below that you can see in the browser:

No comments:

Post a Comment