This post will show you how to create a simple unbound GridView with Edit, Update, Cancel, and Add capabilities. I need this post for my own memory. Maybe it will help you, too. Here's my simple ASP.NET Gridview's HTML (using templated columns):
<asp:GridView ID="gvMyGrid" runat="server"
AutoGenerateColumns="False" ShowFooter="True" OnRowCommand="gvMyGrid_RowCommand"
OnRowUpdating="gvMyGrid_RowUpdating" OnRowEditing="gvMyGrid_RowEditing" OnRowCancelingEdit="gvMyGrid_RowCancelingEdit"> <Columns>
<asp:TemplateField ShowHeader="False">
<EditItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Update"
Text="Update"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" CommandName="Cancel"
Text="Cancel"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" CommandName="Edit"
Text="Edit"></asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
<asp:LinkButton ID="linkAdd" runat="server" CommandName="ADD">Add</asp:LinkButton>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SomeID" SortExpression="SomeID">
<EditItemTemplate>
<asp:Label ID="lblSomeID" runat="server" Text='<%# Bind("SomeID") %>'></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblSomeID" runat="server" Text='<%# Bind("SomeID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SomeText" SortExpression="SomeText">
<EditItemTemplate>
<asp:TextBox ID="txtSomeText" runat="server" Text='<%# Bind("SomeText") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblSomeText" runat="server" Text='<%# Bind("SomeText") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="txtNewText" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<table><tr><td><asp:LinkButton ID="linkAddEmptyTemplate" runat="server" CommandName="ADD_FROMEMPTY">Add</asp:LinkButton></td><td> Desc:</td><td><asp:TextBox ID="txtNewText_FROMEMPTY" runat="server"></asp:TextBox></td></tr></table>
</EmptyDataTemplate>
</asp:GridView>
Ok, so we have a gridview with an uneditable ID and a Text Field.
Tearing this a apart a bit. We put an extra row in the footer that contains an extra Text field and an Add button. We also have a table containing another Add button and a Text Field in the EmptyDataTemplate. This means that we will always have an add option.
So here's the code (again this is a simple example) that makes this all work (yep, it's C# <grin />):
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGidData();
}
// default the footer to visible
gvMyGrid.ShowFooter = true;
}
// Binds data for the entire example
protected void BindGridViewData()
{
// TODO: Substitute your own DataObject and RetrievalRoutine
MyDataObject obj = SomeClass.SomeRoutineToGetData();
gvMyGrid.DataSource = obj;
gvMyGrid.DataBind();
}
// called by the front end when a linkbutton is pushed
protected void gvMyGrid_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Substring(0,3) == "ADD")
{
string SomeText = "";
// based on the Command name retrieve the data
if(e.CommandName == "ADD")
{
SomeText = ((TextBox)gvMyGrid.FooterRow.FindControl("txtNewText")).Text;
}
else
{
// This was a piece of voodoo that I had to figure out.
// when the grid is empty
// gvMyGrid.Controls[0].Controls[0] will be a GridViewRow containing the controls
// in the empty data template
. SomeText = ((TextBox)((GridViewRow)gvMyGrid.Controls[0].Controls[0]).FindControl("txtNewDescription_FROMEMPTY")).Text;
}
// TODO: add code to do your actual insert
BindGridViewData();
}
}
// Called when the record will be edited. You need to manually set the edit index
protected void gvMyGrid_RowEditing(object sender, GridViewEditEventArgs e)
{
gvMyGrid.EditIndex = e.NewEditIndex;
gvMyGrid.ShowFooter = false; // We also turn off the add screen while updating data
BindGridViewData();
}
// Fires when the Cancel button is clicked
protected void gvMyGrid_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
gvMyGrid.EditIndex = -1;
BindGridViewData();
}
// This record fires when the Update button is clicked
protected void gvMyGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// use the EditIndex property and the rows collection to retrieve a reference tot he individual edit controls
int SomeID = Convert.ToInt32(((Label)((gvMyGrid.Rows[gvMyGrid.EditIndex].Cells[1].FindControl("lblSomeID")))).Text)
string SomeText = ((TextBox)((gvMyGrid.Rows[gvMyGrid.EditIndex].Cells[2].FindControl("txtSomeText")))).Text);
// TODO:Save your Data
gvMyGrid.EditIndex = -1;
BindGridViewData();
}
}
So the promise is that they fixed the DataGrid by giving us the GridView... they've come a long way, and this is very workable for me. If you can use the bound stuff then no code is needed, but if not (as was what seemed to be the case for me)... you can use this.