c# - 在 Web 应用程序中使用 C# 在 asp:GridView 中复制粘贴一行
问题描述
所以我有一个使用 GridView 的 Web 应用程序。我们目前一次添加 1 个新的空白记录,填写并继续。有时需要输入的数据有多个需要复制的字段。有没有办法添加一个空白行,将其填充,然后复制该行并将其粘贴回 GridView?
我看过克隆,但我没有看到任何在 Web 应用程序中有效的东西。感谢您的任何建议。
解决方案
好吧,一种方法,你可以在网格中添加一个复制按钮吗?
假设我们有这个网格:
<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 控件中拖放,而不必用“项目模板”围绕它们,这又是太多的工作和努力。
推荐阅读
- python - Base64 图像比较
- angular - 由于空间问题,日期选择器(覆盖)顶部隐藏
- angular - Angular - 链接到 ViewChild 的函数执行两次
- c++ - 将返回类型专门用于 void 或 const 左值引用
- makefile - 清理目标文件后Make不会重新编译
- mysql - 在 MySQL 中使用 Python 从数组中插入多个值
- python - 为什么从 sprite 类中省略 update() 会影响组方法调用?
- mysql - MySql 错误:与 sql_mode=only_full_group_by 不兼容
- vue.js - 转到 v-data-table 中的下一页结果时滚动到顶部
- python - 如何为 QTableWidget 设置选择滑块?