首页 > 解决方案 > 在 Web 应用程序中使用 C# 在 asp:GridView 中复制粘贴一行

问题描述

所以我有一个使用 GridView 的 Web 应用程序。我们目前一次添加 1 个新的空白记录,填写并继续。有时需要输入的数据有多个需要复制的字段。有没有办法添加一个空白行,将其填充,然后复制该行并将其粘贴回 GridView?

我看过克隆,但我没有看到任何在 Web 应用程序中有效的东西。感谢您的任何建议。

标签: c#asp.netgridview

解决方案


好吧,一种方法,你可以在网格中添加一个复制按钮吗?

假设我们有这个网格:

       <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" 
            cssclass="table table-hover borderhide">
            <Columns>
                <asp:TemplateField HeaderText ="First Name">
                    <ItemTemplate>
                        <asp:TextBox ID="txtFirst" runat="server" Text = '<%# Eval("FirstName") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText ="Last Name">
                    <ItemTemplate>
                        <asp:TextBox ID="txtLast" runat="server" Text = '<%# Eval("LastName") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText ="City">
                    <ItemTemplate>
                        <asp:TextBox ID="txtCity" runat="server" Text = '<%# Eval("City") %>'></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                  <asp:TemplateField HeaderText ="Active">
                    <ItemTemplate>
                        <asp:CheckBox ID="Active" runat="server" Checked = '<%# Eval("Active") %>'></asp:CheckBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText ="Copy">
                    <ItemTemplate>
                        <asp:ImageButton ID="cmdCopy" runat="server" Text="Copy"
                            ImageUrl="~/Content/copy1600.png" Height="32px" Width="32px" 
                            OnClick="cmdCopy_Click" />
                    </ItemTemplate>
                </asp:TemplateField>


            </Columns>
        </asp:GridView>
            <asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn-primary" OnClick="cmdSave_Click1" />

            <asp:Button ID="cmdAdd" runat="server" Text="Add Row" CssClass="btn-primary" style="margin-left:20px" OnClick="cmdAdd_Click1"/>
            <br />

所以,加载这个网格的代码

    private DataTable rstPeople = new DataTable();

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
        LoadGrid();
        ViewState["MyTable"] = rstPeople;
    }
    else
        rstPeople = (DataTable)ViewState["MyTable"];

    }
    public void LoadGrid()
    {
        using (SqlCommand cmdSQL = new SqlCommand("SELECT * from People", 
                                    new SqlConnection(Properties.Settings.Default.TEST4)))
        {
            cmdSQL.Connection.Open();

            rstPeople.Load(cmdSQL.ExecuteReader());

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

以及添加行按钮代码:

   protected void cmdAdd_Click1(object sender, EventArgs e)
    {

        GridToTable();      // user may have edits
        // add a new row to the grid

        DataRow OneRow = rstPeople.NewRow();
        OneRow["Age"] = 0;
        OneRow["Active"] = true;
        rstPeople.Rows.Add(OneRow);
        GridView1.DataSource = rstPeople;
        GridView1.DataBind();
    }

所以我们点击添加行,这给了我们这个:

在此处输入图像描述

所以,我们有那个空白行。但是,代替添加行,我们可以单击复制按钮,这将添加一行 - 但从当前复制。(我想我们可以有一个复制 + 粘贴按钮 - 但这里的 UI 太多了)。

因此,添加行 = 添加空白行。

但是,复制行按钮 - 添加行 - 复制。

代码如下所示:

   protected void cmdCopy_Click(object sender, ImageClickEventArgs e)
    {

        GridToTable();      // user might have done some editing

        ImageButton cmdCopy = (ImageButton)sender;
        GridViewRow gvRow = (GridViewRow)cmdCopy.Parent.Parent;

        DataRow CopyFrom = rstPeople.Rows[gvRow.RowIndex];

        DataRow OneRow = rstPeople.NewRow();
        OneRow["Age"] = 0;
        OneRow["FirstName"] = CopyFrom["FirstName"];
        OneRow["LastName"] = CopyFrom["LastName"];
        OneRow["City"] = CopyFrom["City"];
        OneRow["Active"] = CopyFrom["Active"];

        rstPeople.Rows.Add(OneRow);
        GridView1.DataSource = rstPeople;
        GridView1.DataBind();

    }

现在我没有分享保存按钮的工作原理。

因此,用户现在可以添加新行。选项卡 - 编辑任何行。甚至复制一个新行(再次编辑一些)。

所以将整个混乱和网格保存回数据库,我们

 Send Grid back to table
 Send table back to database.

所以保存所有按钮是这样的:

   protected void cmdSave_Click1(object sender, EventArgs e)

    {
        GridToTable();

        // now send table back to database with updates
        string strSQL = "SELECT ID, FirstName, LastName, City, Active from People WHERE ID = 0";

        using (SqlCommand cmdSQL = new SqlCommand(strSQL, 
                                    new SqlConnection(Properties.Settings.Default.TEST4)))
        {
            cmdSQL.Connection.Open();
            SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
            SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);

            daupdate.Update(rstPeople);
        }
    }

再次,真的很简单。并注意我们是如何不打扰模板等的(太乱了,而且确实不比上面的代码少)。

我想您可以为新行添加一个“粘贴”图标,但如果用户必须选择一行并复制 - 不妨在一次操作中将其设为“添加行 + 复制”。

(它不是真正的复制按钮,而是更多的“复制行”按钮。

唯一未发布的例程是 GridToTable。这是可行的,因为我们总是持久化表,但是 GV 中的任何编辑都必须发送回表,因此我们使用这个:

   void GridToTable()
    {
        // pull grid rows back to table.
        foreach (GridViewRow rRow in GridView1.Rows)
        {
            int RecordPtr = rRow.RowIndex;
            DataRow OneDataRow;
            OneDataRow = rstPeople.Rows[RecordPtr];
            OneDataRow["FirstName"] = ((TextBox)rRow.FindControl("txtFirst")).Text;
            OneDataRow["LastName"] = ((TextBox)rRow.FindControl("txtLast")).Text;
            OneDataRow["City"] = ((TextBox)rRow.FindControl("txtCity")).Text;
            OneDataRow["Active"] = ((CheckBox)rRow.FindControl("Active")).Checked;
        }
    }

如前所述,我想您可以放入“复制”按钮,并且仅保留+保存行索引,然后使用粘贴按钮-这将允许在任何行之间进行剪切+粘贴,而不仅限于新行。(但是,这将允许用户很容易地覆盖现有行 - 从用户培训的角度来看,UI 再次过载。

上面的技巧非常巧妙,因为任何新行、任何编辑都会通过一个简单的更新操作发送回数据库。(并且提供者很聪明 - 如果没有触及或更改一行,则不会生成 sql 更新语句。

由于将表保留在 ViewState 中,这整个技巧有效。请注意,如果您有数据分页器,则必须在此类导航中调用 GridToTable,或者实际上执行保存命令。

还要注意我们是如何选择 .parent.parent (网格行)的,并且再次没有使用 GV 事件模型。并且没有大量模板的东西,我们也不必与多个模板混淆,从而拯救了世界的贫困。

事实上,对于上述之外的任何网格,我都使用与上述完全相同的方法,但更喜欢 ListView。原因是您可以在标准的 asp.net 控件中拖放,而不必用“项目模板”围绕它们,这又是太多的工作和努力。


推荐阅读