在 Web 应用程序中使用 C# 在 asp:GridView 中复制粘贴一行

Posted

技术标签:

【中文标题】在 Web 应用程序中使用 C# 在 asp:GridView 中复制粘贴一行【英文标题】:Copy Paste a row in a asp:GridView using C# in a web application 【发布时间】:2021-11-10 20:05:28 【问题描述】:

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

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

【问题讨论】:

您是在服务器上还是在客户端上添加行?有很多方法可以使用 GridView,也有很多方法可以添加一行。您只需要在新行上设置初始值。 目前我将空白行添加到sqlserver,然后填写并更新GV以及sql server。更新行后,我希望能够复制行并将其插入服务器,然后返回更新必要的字段。 【参考方案1】:

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

假设我们有这个网格:

       <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 控件中拖放,而不必用“项目模板”围绕它们,这又是太多的工作和努力。

【讨论】:

哇哦...很多。让我消化一下,明天再回复。谢谢你的努力。非常感激!!我的gridview中的绑定字段通常是一样的吗?谢谢 当然,在我的示例中,行是数据绑定的。但我不使用额外的模板进行编辑或添加,因为我们真的不需要它们。但是,如果您仔细观察,我使用了模板列,但如果您使用绑定字段,那么我们使用 .cells[] 集合代替 FindControl - 代码将大致相同,但没有查找控件。我想我们也可以全力以赴,并添加一个 javascript 右键单击​​以复制 - 这是可能的,但这是简单的服务器端代码 - 如此干净和容易。 --- 唯一真正的区别是 .cells[] 集合是按列号 - 不是名称,但其他一切都是一样的。 很难复制选定的行。我看到你提到它应该是数字,但它是如何抓取的? 仔细查看我放入网格的按钮。仔细查看上面名为 cmdCopy_Click 的按钮存根事件。它首先将网格复制回表格(如果您允许网格编辑)。然后它获取/抓取您使用 cmdCopy.Parent.Parent 单击的行。那是用户单击的行。然后我从该行获取行索引,然后简单地添加一个新行,从该网格行复制值,然后重新绑定网格以显示我们刚刚添加的这个新行。所以 cmdCopy.Parent.Parent 是单击按钮事件如何获取当前网格行(我将其转换为 GridViewRow)。 获得整个网格行后,我可以将值从该网格行复制到新行。但是,由于我有表持久化,所以我只需将行索引获取到我正在更新的现有表。因此,我使用该表行中的值来设置用于添加的新行的值。设置值,将新行添加到数据表中,然后重新绑定网格以显示此新行。所以,我真的不必从网格行中获取/获取值,因为该网格行让我将索引行放入表中。但是,如果我没有持久表,我可以从网格中复制。

以上是关于在 Web 应用程序中使用 C# 在 asp:GridView 中复制粘贴一行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio 2019 中使用 Xamarin Forms(UWP) 和 C# 创建 Web 应用程序

在 C# Web 应用程序中从网络共享访问文件

在 ASP.NET C# Web 应用程序中使用 ADO.NET 和 XML

如何在asp.net c# web应用程序中使用asp.net vb页面

如何在 C# 的控制台应用程序中使用带有 Web 浏览器的计时器?

C# PowerShell 无法仅在 Web 应用程序中连接到 AzureAD