In this article I will explain how to perform required validation for automatically generated TextBoxes for BoundField columns in Edit mode of GridView in ASP.Net using C# and VB.Net.
By default when GridView Row is edited, the BoundField columns get converted to TextBoxes but there is no provision to validate these TextBoxes.
HTML Markup
The following HTML Markup consists of an ASP.Net GridView.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowCreated = "OnRowCreated" OnRowEditing="OnRowEditing">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" ItemStyle-Width="150" />
<asp:BoundField DataField="Country" HeaderText="Country" ItemStyle-Width="150" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID = "lnkEdit" Text="Edit" runat="server" CommandName="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID = "lnkUpdate" Text="Update" runat="server" OnClick="OnUpdate" />
<asp:LinkButton ID = "lnkCancel" Text="Cancel" runat="server" OnClick="OnCancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Namespaces
You will need to import the following namespaces.
C#
using System.Data;
using System.Drawing;
VB.Net
Imports System.Data
Imports System.Drawing
Populating the GridView with a dynamic temporary DataTable
Inside the Page Load event handler of the page, I am first creating a dynamic temporary DataTable object, adding columns to it and then adding some data to the DataTable.
Then this dynamic temporary DataTable is saved in a ViewState variable and finally it is used to populate the GridView control.
Note: You can use database backend and make use of ADO.Net or SqlDataSource.
C#
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[3] { new DataColumn("Id"), new DataColumn("Name"), new DataColumn("Country") });
dt.Rows.Add(1, "John Hammond", "United States");
dt.Rows.Add(2, "Mudassar Khan", "India");
dt.Rows.Add(3, "Suzanne Mathews", "France");
dt.Rows.Add(4, "Robert Schidner", "Russia");
ViewState["dt"] = dt;
this.BindGrid();
}
}
protected void BindGrid()
{
GridView1.DataSource = ViewState["dt"] as DataTable;
GridView1.DataBind();
}
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not Me.IsPostBack Then
Dim dt As New DataTable()
dt.Columns.AddRange(New DataColumn(2) {New DataColumn("Id"), New DataColumn("Name"), New DataColumn("Country")})
dt.Rows.Add(1, "John Hammond", "United States")
dt.Rows.Add(2, "Mudassar Khan", "India")
dt.Rows.Add(3, "Suzanne Mathews", "France")
dt.Rows.Add(4, "Robert Schidner", "Russia")
ViewState("dt") = dt
Me.BindGrid()
End If
End Sub
Protected Sub BindGrid()
GridView1.DataSource = TryCast(ViewState("dt"), DataTable)
GridView1.DataBind()
End Sub
OnRowEditing event handler
Below is the OnRowEditing event handler which will be triggered for a GridView Row when the edit button inside that row is clicked.
Inside this event handler, I am setting the GridView EditIndex with the NewEditIndex fetched from the GridViewEditEventArgs object and then the GridView is again populated from the temporary DataTable stored inside the ViewState variable.
The above process sets the GridView in Edit Mode and the BoundField columns get converted to TextBox automatically.
C#
protected void OnRowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
this.BindGrid();
}
VB.Net
Protected Sub OnRowEditing(sender As Object, e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
Me.BindGrid()
End Sub
Note: If you do not want a particular BoundField column to get converted to TextBox in Edit Mode, you need to set the ReadOnly property to True.
Dynamically adding RequiredField Validator inside the OnRowCreated event handler
Inside the OnRowCreated event handler, if the GridView Row is being edited, then a loop is executed over all its cells.
Inside the loop, a check is made to find whether the Cell contains a TextBox control. If the Cell contains TextBox control, then the TextBox is assigned an ID and a dynamic RequiredField Validator is added to the Cell.
Note: The automatically generated TextBoxes in Edit Mode do not have any ID assigned. Since we need to add a RequiredField Validator to the TextBox, we will need to assign them an ID.
If the Cell does not contain any TextBox controls then it must be the Cell containing the Update and Cancel LinkButtons. The Update LinkButton is assigned a ValidationGroup same as that of the RequiredField Validator.
Note: ValidationGroup is set for the RequiredField Validator and the Update LinkButton so that it does the validation does not fire when other Buttons are clicked.
C#
protected void OnRowCreated(object sender, GridViewRowEventArgs e)
{
//Find the Row being edited.
if (GridView1.EditIndex == e.Row.RowIndex)
{
//Loop through all Cells in the Row.
int index = 0;
foreach (TableCell cell in e.Row.Cells)
{
if (cell.Controls.Count > 0)
{
//Check whether Cell has TextBox.
if (cell.Controls[0] is TextBox)
{
//Reference the TextBox.
TextBox textBox = cell.Controls[0] as TextBox;
//Assign ID to the TextBox.
textBox.ID = "txt" + GridView1.HeaderRow.Cells[index].Text.Replace(" ", "");
//Create and assign RequiredFieldValidator to the TextBox.
RequiredFieldValidator validator = new RequiredFieldValidator
{
ControlToValidate = textBox.ID,
ForeColor = Color.Red,
ErrorMessage = "Required",
ValidationGroup = "Update"
};
cell.Controls.Add(validator);
}
else
{
//Add ValidationGroup to the Update Button.
LinkButton lnkUpdate = cell.FindControl("lnkUpdate") as LinkButton;
lnkUpdate.ValidationGroup = "Update";
}
}
index++;
}
}
}
VB.Net
Protected Sub OnRowCreated(sender As Object, e As GridViewRowEventArgs)
'Find the Row being edited.
If GridView1.EditIndex = e.Row.RowIndex Then
'Loop through all Cells in the Row.
Dim index As Integer = 0
For Each cell As TableCell In e.Row.Cells
If cell.Controls.Count > 0 Then
'Check whether Cell has TextBox.
If TypeOf cell.Controls(0) Is TextBox Then
'Reference the TextBox.
Dim textBox As TextBox = TryCast(cell.Controls(0), TextBox)
'Assign ID to the TextBox.
textBox.ID = "txt" + GridView1.HeaderRow.Cells(index).Text.Replace(" ", "")
'Create and assign RequiredFieldValidator to the TextBox.
Dim validator As New RequiredFieldValidator() With { _
.ControlToValidate = textBox.ID, _
.ForeColor = Color.Red, _
.ErrorMessage = "Required", _
.ValidationGroup = "Update" _
}
cell.Controls.Add(validator)
Else
'Add ValidationGroup to the Update Button.
Dim lnkUpdate As LinkButton = TryCast(cell.FindControl("lnkUpdate"), LinkButton)
lnkUpdate.ValidationGroup = "Update"
End If
End If
index += 1
Next
End If
End Sub
GridView Row Update and Cancel Edit Events
Below are the event handlers for the Update and the Cancel buttons.
Inside the Update event handler, the temporary DataTable is fetched back from the ViewState variable and then the row to be updated is identified using the RowIndex of the GridView Row whose Update button was clicked.
Then the values to be updated are fetched from the TextBoxes and are assigned to the respective columns of the DataTable Row.
Finally the temporary DataTable is saved back in ViewState and the GridView is again populated with the updated temporary DataTable.
Inside the Cancel event handler, the GridView EditIndex is set to -1 and the GridView is populated with data from the temporary DataTable saved in ViewState.
C#
protected void OnUpdate(object sender, EventArgs e)
{
GridViewRow row = (sender as LinkButton).NamingContainer as GridViewRow;
string name = (row.Cells[0].Controls[0] as TextBox).Text;
string country = (row.Cells[1].Controls[0] as TextBox).Text;
DataTable dt = ViewState["dt"] as DataTable;
dt.Rows[row.RowIndex]["Name"] = name;
dt.Rows[row.RowIndex]["Country"] = country;
ViewState["dt"] = dt;
GridView1.EditIndex = -1;
this.BindGrid();
}
protected void OnCancel(object sender, EventArgs e)
{
GridView1.EditIndex = -1;
this.BindGrid();
}
VB.Net
Protected Sub OnUpdate(sender As Object, e As EventArgs)
Dim row As GridViewRow = TryCast(TryCast(sender, LinkButton).NamingContainer, GridViewRow)
Dim name As String = TryCast(row.Cells(0).Controls(0), TextBox).Text
Dim country As String = TryCast(row.Cells(1).Controls(0), TextBox).Text
Dim dt As DataTable = TryCast(ViewState("dt"), DataTable)
dt.Rows(row.RowIndex)("Name") = name
dt.Rows(row.RowIndex)("Country") = country
ViewState("dt") = dt
GridView1.EditIndex = -1
Me.BindGrid()
End Sub
Protected Sub OnCancel(sender As Object, e As EventArgs)
GridView1.EditIndex = -1
Me.BindGrid()
End Sub
Screenshot
Demo
Downloads