简体   繁体   中英

How to add Delete link in GridView while adding new row from C#?

GridView contains ShowDeleteButton CommandField along with other textbox fields.

I'm adding new row to this grid in C# that is adding new textboxes for each newly added row. How to add Delete link while adding new row?

<asp:GridView ID="Gridview1" runat="server" ShowFooter="true" OnRowDataBound="Gridview1_OnRowDataBound" OnRowDeleting="Gridview1_RowDeleting" AutoGenerateColumns="false" ShowHeaderWhenEmpty="True" EmptyDataText="No Record Available"> <asp:TemplateField HeaderText="Question"> <asp:TextBox ID="txtQuestion" runat="server" Text='<%# Eval("Question") %>'></asp:TextBox> </asp:TemplateField>

            <asp:TemplateField HeaderText="Answer">
                <ItemTemplate>
                    <asp:TextBox ID="txtAnswer" ReadOnly="true" Enabled="false" runat="server" Text='<%# Eval("Answer") %>'></asp:TextBox>
                </ItemTemplate>
                <FooterStyle HorizontalAlign="Right" />
                <FooterTemplate>
                    <asp:Button ID="btnAddNewQuestionnaire" runat="server" Text="Add New Row" OnClick="btnAddNewQuestionnaire_Click" />
                </FooterTemplate>
            </asp:TemplateField>
        
            <asp:CommandField ShowDeleteButton="true"  /> 
        </Columns>
        </asp:GridView>
        
              
               
        
        private void AddNewRow()
        {   
            DataTable dt = new DataTable();
            DataRow dr;
            dt.Columns.Add(new System.Data.DataColumn("Question", typeof(String)));
            dt.Columns.Add(new System.Data.DataColumn("Answer", typeof(String)));
        
            foreach (GridViewRow row in Gridview1.Rows)
            {
                TextBox txtQuestion = (TextBox)row.FindControl("txtQuestion");
                TextBox txtAnswer = (TextBox)row.FindControl("txtAnswer");
                dr = dt.NewRow();
                dr[0] = txtQuestion.Text;
                dr[1] = txtAnswer.Text;
                dt.Rows.Add(dr);
            }
        
            dt.Rows.Add(dt.NewRow());
            dt.Rows[dt.Rows.Count - 1]["Question"] = "";
            dt.Rows[dt.Rows.Count - 1]["Answer"] = "";
        
            dt.AcceptChanges();
        
            Gridview1.EditIndex = dt.Rows.Count - 1;
            Gridview1.DataSource = dt;
            Gridview1.DataBind();
        
        }

I recommend that you simple add the delete button to each row. That way the user can easy delete a row.

I also recommend that you load the grid one time with the datatable, and then add the row to the datatable - NOT the grid.

I could write tuckloads of advantages of this approach. But some advantages are:

user does not get presented with multiple UI
user can edit any row on the grid - not have to hit edit, or save
a single un-do button can un-do all changes
a single SAVE button in ONE operation can save the WHOLE TABLE and change back to database

Your code to add a row, and the code to setup and create the database are seperate. This means that you can change the data table, or even have the source of the table come from sql server. And as noted, this also allows you to save the WHOLE table. The result is the user can edit one rows, many rows - tab around MUCH like a excel spreadsheet. When done, they can:

 hit save - all data back to database
 hit un-do - un-do all their edits
 hit + (add row) - add a new row to edit
 hit delete key - it will delete the row in question (but UN-DO STILL ACTIVE!!!).

so we have a far more pleasant way to edit.

And thus, I suggest you don't use the built in delete button. Drop in your own button - it will look nicer anyway. (and thus no edit button required either.!!!).

So, here is our markup:

       <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:ImageButton ID="ImageButton1" runat="server" 
                            ImageUrl="~/Content/uncheck1.jpg" Height="35px" Width="45px" 
                             OnClick="ImageButton1_Click"
                             MyRowID = '<%# Container.DataItemIndex %>' />
                    </ItemTemplate>
                </asp:TemplateField>
                
                <asp:TemplateField HeaderText="Question">
                    <ItemTemplate>
                    <asp:TextBox ID="txtQuestion" runat="server" Text='<%# Eval("Question") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

            <asp:TemplateField HeaderText="Answer">
                <ItemTemplate>
                    <asp:TextBox ID="txtAnswer"  runat="server" Text='<%# Eval("Answer") %>'></asp:TextBox>
                </ItemTemplate>
             </asp:TemplateField>
            </Columns>

        </asp:GridView>
        <br />
        <asp:Button ID="btnAddNewQuestionnaire" runat="server" Text="+Add New Row" OnClick="btnAddNewQuestionnaire_Click" />

When you drop the button (I used a image button), then in the code editor do this:

在此处输入图像描述

Note how RIGHT after you hit "=" then intel-sense pops up - choose create new event. It looks like NOTHING occurs, but if you flip over to code behind, you see a code sub was generated. You can't double click on the controls inside the grid, but you CAN create a event click for a button - or in fact any event for a standard asp.net control this way.

I also to save world poverties also added a custom attribute to that button called MyRowID - this will set the row index for that button.

Since the add new row button is OUTSIDE of the grid, then we can just double click on that button, and jump to the code behind.

Now, our code looks like this:

private DataTable MyTable = new DataTable();

protected void Page_Load(object sender, System.EventArgs e)
{
    if (IsPostBack == false)
    {
        LoadGrid();
        ViewState["MyTable"] = MyTable;
    }
    else
        MyTable = ViewState["MyTable"];
}

public void LoadGrid()
{
    MyTable.Columns.Add(new DataColumn("Question", typeof(string)));
    MyTable.Columns.Add(new DataColumn("Answer", typeof(string)));

    GridView1.DataSource = MyTable;
    GridView1.DataBind();
}

protected void btnAddNewQuestionnaire_Click(object sender, EventArgs e)
{
    DataRow MyRow = MyTable.NewRow;
    MyRow("Question") = "my question";
    MyRow("Answer") = "my ans";

    MyTable.Rows.Add(MyRow);
    GridView1.DataSource = MyTable;
    GridView1.DataBind();
}

protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
    ImageButton btn = sender;
    int RowID = btn.Attributes.Item("MyRowID");

    MyTable.Rows(RowID).Delete();
    GridView1.DataSource = MyTable;
    GridView1.DataBind();
}

Note VERY carefull - we added a MyTable to the form class. Thus we have a persited table, and we operate against that table.

In fact, the EXACT same above desing can be used if the data came from SQL server. And not only MORE amazing, but we can NOW thus SAVE + SEND the whole table BACK to sql server in one update operation. (you just loop the grid, put values back into table, and execute one save).

And the above has no messy edit button to edit a row. and I suppose we COULD add for extra marks a delete conformation box - the user if they bump or hit delete button, they would get a confirm dialog box. That code could be this:

  <asp:ImageButton ID="ImageButton1" runat="server" 
     ImageUrl="~/Content/uncheck1.jpg" Height="35px" Width="45px" 
     OnClick="ImageButton1_Click"
     MyRowID = '<%# Container.DataItemIndex %>'
     OnClientClick="return confirm('Delete this row?');"/>

So now when you hit delete row, you get this:

在此处输入图像描述

If you click ok - it deletes - cancel - nothing occurs.

So, you can save a LOT of code and complexity here with:

Persist the data table
Pass the row ID with the button
use the intel-sense trick to wire up a separate and specific button event code.

As noted, this whole above process would ALSO work if you load the table with data from sql server - the REST of the code "as is" will work.

And to save the data back to sql server, then you can as noted:

Pull data from grid back to that persisted table. And then with a data adaptor, ONE update command will send all changes back to sql server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM