[转][ASP.NET]How to easily insert row in GridView with SqlDataSource?

Asp.Net 2.0 GridView control is very powerful control. Developers at Microsoft really did a great job when designing it.
Its like Swiss Army knife for selecting, editing, sorting, paging and displaying data.
Combined with various DataSource controls (ObjectDataSource, SqlDataSource) it helps you execute most of your Read, Update and Delete operations without writing a single line of code.
Off course, nothing is perfect. For example, creating new data is is one common task that is not so simple to accomplish with GridView.
Since there is InsertCommand property in DataSource controls that we can set to insert data, there is no reason not to use it with GridView to insert new data, just like we use DeleteCommand to delete data.
For some strange reason there is no built-in way to do this, but there are always workarounds .
Let see how we can insert new rows of data using GridView and SqlDataSource:
For this tutorial we will use Visual Studio 2005 (VS 2008 is also fine) and MSSql Server 2005 Express (with user instances enabled).
(You can download the full working solution for Visual Studio 2005 right HERE if you want to skip the talk and just look at the code but i strongly suggest that you read the whole article to completely understand all the details).
Ok, let us start by opening the Visual Studio and creating new Solution and adding new Asp.Net Website to that Solution.
In our website we will create a new local (user instance) MSSQL Server 2005 Express database in our App_Data subfolder (if there is no App_Data subfolder in your website you can create it by right-mouse-clicking on the website in Solution Explorer and choosing the option Add Asp.Net Folder -> App_Data).
To add local database to your App_Data folder just right-mouse-click on the folder in Solution Explorer and choose:
Add New Item -> SQL Database.
Give it some meaningful name like InsertRowsWithGridView.mdf and create a connection string for it in your web.config like this:

    <connectionStrings>
<add name="localDBConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\InsertRowsWithGridView.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
</connectionStrings>

Now we can create one sample table in this database (right-mouse-click on the database in App_Data folder we just created and then choose Open and ServerExplorer window will pop-up and there you can edit the database, create new tables etc).
Right-Mouse-Click on Tables row in ServerExplorer and add new table to database and call it Customers.
Our simple table will have only 3 columns:

  1. CustomerId - Int, PrimaryKey, Identity Column with seed and increment 1
  2. FirstName - VarChar(30)
  3. LastName - VarChar(30)

Table definition
Just to mention its a minimal and not very real-world database and table schema but it will work just fine for the sake of this example.
Now that we have our database table ready, open your Default.aspx page and add to your Form a SqlDataSource control (for example call it CustomersSqlDataSource):

        <asp:sqldatasource ID="CustomersSqlDataSource" runat="server"

        ConnectionString="<%$ ConnectionStrings:localDBConnectionString %>"

SelectCommand="SELECT [CustomerId], [FirstName], [LastName] FROM [Customers] ORDER BY [LastName], [FirstName]"

InsertCommand="Insert into Customers (FirstName, LastName) values (@FirstName, @LastName)"

UpdateCommand="Update Customers set FirstName=@FirstName, LastName=@LastName where CustomerId=@CustomerId"

DeleteCommand="Delete from Customers where CustomerId = @CustomerId"

        </asp:sqldatasource>

Here we added SQL commands to the SqlDataSource that it will use to Select, Insert, Update and Delete the data and also we declaratively assigned a connection string from our web.config file (connectionStrings section) to it.
Now lets create our GridView control. We will connect the GridView with our SqlDataSource, tell it not generate columns for us, and also we will set the DataKeyNames property to our tables PrimaryKey column - CustomerId.
After this we must create TemplateFields for each of our fields.
CustomerId TemplateField will only have ItemTemplate becasue it should not be edited.
On the other hand, FirstName and LastName fields will have both ItemTemplate for displaying and EditItemTemplate for editing, and also a FooterTemplate - this is important part because this is where our TextBox fields for Inserting new Rows will be placed.
Also we will have fourth column where we will place our command Button controls like Edit, Update, Delete and Cancel.
On the bottom of the GridView definition is EmptyDataTemplate where we will put TextBoxes for inserting new rows when there is no data in our database table.
Here is the full GridView declaration:

    <asp:GridView ID="Customers" runat="server" AutoGenerateColumns="False"

DataSourceID="CustomersSqlDataSource" DataKeyNames="CustomerId" ShowFooter="true"

onrowcommand="Customers_RowCommand">

        <Columns>

            <asp:TemplateField HeaderText="CustomerId">

                <ItemTemplate>

                    <%# Eval("CustomerId") %>

                </ItemTemplate>

            </asp:TemplateField>

            <asp:TemplateField HeaderText="FirstName">

                <ItemTemplate>

                    <%# Eval("FirstName") %>

                </ItemTemplate>

                <EditItemTemplate>

                    <asp:TextBox runat="server" ID="EditFirstName" Text=''

                    <%# Bind("FirstName") %>' />

                </EditItemTemplate>

                <FooterTemplate>

                    <asp:TextBox runat="server" ID="InsertFirstName" Text=''

                    <%# Bind("FirstName") %>' />

                </FooterTemplate>

            </asp:TemplateField>

            <asp:TemplateField HeaderText="LastName">

                <ItemTemplate>

                    <%# Eval("LastName") %>

                </ItemTemplate>

                <EditItemTemplate>

                    <asp:TextBox runat="server" ID="EditLastName" Text=''

                    <%# Bind("LastName") %>' />

                </EditItemTemplate>

                <FooterTemplate>

                    <asp:TextBox runat="server" ID="InsertLastName" Text=''

                    <%# Bind("LastName") %>' />

                </FooterTemplate>

            </asp:TemplateField>

            <asp:TemplateField HeaderText="Commands">

                <ItemTemplate>

                    <asp:Button runat="server" ID="Edit" Text="Edit" CommandName="Edit" />

                    <asp:Button runat="server" ID="Delete" Text="Delete" CommandName="Delete" />

                </ItemTemplate>

                <EditItemTemplate>

                    <asp:Button runat="server" ID="Update" Text="Update" CommandName="Update" />

                    <asp:Button runat="server" ID="Cancel" Text="Cancel" CommandName="Cancel" />

                </EditItemTemplate>

                <FooterTemplate>

                    <asp:Button runat="server" ID="Insert" Text="Insert" CommandName="InsertNew" />

                    <asp:Button runat="server" ID="Cancel" Text="Cancel" CommandName="CancelNew" />

                </FooterTemplate>

            </asp:TemplateField>

        </Columns>

        <EmptyDataTemplate>

            First Name:<asp:TextBox runat="server" ID="NoDataFirstName" />

            Last Name:<asp:TextBox runat="server" ID="NoDataLastName" />

            <asp:Button runat="server" ID="NoDataInsert" CommandName="NoDataInsert" Text="Insert"/>

        </EmptyDataTemplate>

    </asp:GridView>

Now when we first start the website here is how our GridView will look like, with no data to show, just fields to insert new rows of data:
GridView with no data
and here is how it will look after we add some fictive data rows to it:
GridViewWithData
Now lets see how to make all this work behind the scenes: 
Since we supplied SelectCommand, UpdateCommand and DeleteCommand in SqlDataSource and added proper TemplatedFields with Buttons that have their CommandName property set to Edit, Update, Cancel and Delete into the GridView declaration, Editing and Deleting of rows will work out-of-the-box.
GridView will cooperate with SqlDataSource to enable users to Update and Delete data to our DB without any hassle.
To enable Inserting of data rows we need to add some custom code to the Page and to the event handlers of GridView and SqlDataSource.
Since we added InsertCommand to SqlDataSource, we only need to find a way to supply parameters with data to this command and to call Insert method of SqlDataSource to have our rows inserted into database.
We will first create on our Page a private generic List collection of SqlParameters where we will temporarily keep our parameters filled with new data row values when we retrieve them from GridView:

// here we keep the SqlParameters that we will use to insert new row

private List<SqlParameter> insertParameters = new List<SqlParameter>();

Now lets handle the RowCommand event of GridView control, that fires when user clicks on the Buttons controls:

protected void Customers_RowCommand(object sender, GridViewCommandEventArgs e)

    {

if (e.CommandName == "NoDataInsert")

        {

TextBox FirstName = Customers.Controls[0].Controls[0].FindControl("NoDataFirstName") as TextBox;

TextBox LastName = Customers.Controls[0].Controls[0].FindControl("NoDataLastName") as TextBox;

SqlParameter fName = new SqlParameter("@FirstName", SqlDbType.VarChar, 30);

            fName.Direction = ParameterDirection.Input;

            fName.Value = FirstName.Text;

            insertParameters.Add(fName);

SqlParameter lName = new SqlParameter("@LastName", SqlDbType.VarChar, 30);

            lName.Direction = ParameterDirection.Input;

            lName.Value = LastName.Text;

            insertParameters.Add(lName);

            CustomersSqlDataSource.Insert();

        }

else if (e.CommandName == "InsertNew")

        {

TextBox FirstName = Customers.FooterRow.FindControl("InsertFirstName") as TextBox;

TextBox LastName = Customers.FooterRow.FindControl("InsertLastName") as TextBox;

SqlParameter fName = new SqlParameter("@FirstName", SqlDbType.VarChar, 30);

            fName.Direction = ParameterDirection.Input;

            fName.Value = FirstName.Text;

            insertParameters.Add(fName);

SqlParameter lName = new SqlParameter("@LastName", SqlDbType.VarChar, 30);

            lName.Direction = ParameterDirection.Input;

            lName.Value = LastName.Text;

            insertParameters.Add(lName);

            CustomersSqlDataSource.Insert();

        }

    }

what happens here is that we first find out what button initiated the event, and according to that we find the TextBox controls that hold the First and Last name values that user entered.
If command name is NoDataInsert than user is inserting the first row in our table and we need to find TextBox controls from EmptyDataTemplate.
If the command name is InsertNew then we know that user is adding new rows to the table that already has some data rows, and we need to look for values in TextBoxes in the Footer of the GridView.
Once we find the right TextBox controls using the FindControl command, we fetch their values and create SqlParameters with those values and store them into our private generic List of SqlParameters we created earlier.
Then we can simply call Insert method of the SqlDataSource.
Now the hard part of the work is done. We only need to add some code to the handler of Inserting event of the SqlDataSource that fires BEFORE inserting is done, to assign those parameters to the InsertCommand like this:

protected void Sqldatasource1_Inserting(object sender, SqlDataSourceCommandEventArgs e)

    {

        e.Command.Parameters.Clear();

foreach (SqlParameter p in insertParameters)

            e.Command.Parameters.Add(p);

    }

And this is it. When the SqlDataSource InsertCommand is invoked (the one we called in RowCommand handler) it will already have all the parameters it needs to insert new data to the database!
Visual Studio 2005 Solution download for this tutorial:
InsertRowsWithGridViewAndSqlDataSource_solution.zip

来自:http://www.aspdotnetfaq.com/Faq/How-to-insert-row-in-GridView-with-SqlDataSource.aspx

posted @ 2010-12-01 09:27  laughter  阅读(599)  评论(0编辑  收藏  举报