好的,所以我们这里需要两个部分:
我们需要(想要)持久化驱动网格的数据表)。
这样做的原因是什么?
我们用一块石头杀死了大约 3 只鸟。
我们使用数据表store/save/know the deleted state
我们使用该删除信息来切换我们的图像
(因此不必将状态存储在网格视图中)。
我们还可以使用该表状态一次性更新数据库,因此不必编写一堆数据库操作(删除行)。我们只是将表发送回数据库。
其实在这个例子中,我可以添加大约 7 行代码,如果你用 tab 键来编辑数据?它也将被发送回数据库。这意味着没有杂乱的编辑模板和所有的爵士乐(无论如何都是泛滥的)。
好的,这里是我们的网格 - 只是一些酒店 - 以及带有图像的删除按钮:
标记:
<div style="width:40%;margin-left:20px">
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table table-hover borderhide" >
<Columns>
<asp:TemplateField HeaderText="HotelName" >
<ItemTemplate><asp:TextBox id="HotelName" runat="server" Text='<%# Eval("HotelName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="FirstName" SortExpression="ORDER BY FirstName" >
<ItemTemplate><asp:TextBox id="FirstName" runat="server" Text='<%# Eval("FirstName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="LastName" >
<ItemTemplate><asp:TextBox id="LastName" runat="server" Text='<%# Eval("LastName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City" >
<ItemTemplate><asp:TextBox id="City" runat="server" Text='<%# Eval("City") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete">
<ItemTemplate>
<asp:ImageButton ID="cmdDelete" runat="server" Height="20px" Style="margin-left:10px"
ImageUrl="~/Content/cknosel.png"
Width="24px" OnClick="cmdDelete_Click"></asp:ImageButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<asp:Button ID="cmdDeleteAll" runat="server" Text="Delete selected" Width="122px"
OnClientClick="return confirm('Delete all selected?')" />
</div>
好的,加载网格的代码 - 注意我们持久化数据表!!!!!
代码:
DataTable rstTable = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
else
rstTable = (DataTable)ViewState["rstTable"];
}
void LoadGrid()
{
// load up our grid
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels ORDER BY HotelName ",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstTable.Clear();
rstTable.Load(cmdSQL.ExecuteReader());
GridView1.DataSource = rstTable;
GridView1.DataBind();
}
ViewState["rstTable"] = rstTable;
}
好的,到目前为止,很简单的简。结果是这样的:
好的,现在我们只需要添加删除按钮点击事件。
该代码如下所示:
protected void cmdDelete_Click(object sender, ImageClickEventArgs e)
{
ImageButton btn = (ImageButton)sender;
GridViewRow rRow = (GridViewRow)btn.Parent.Parent;
DataRow OneRow = rstTable.Rows[rRow.DataItemIndex];
// toggle data
if (OneRow.RowState == DataRowState.Deleted)
{
// undelete
OneRow.RejectChanges();
btn.ImageUrl = "/Content/cknosel.png";
}
else
{
// delete
OneRow.Delete();
btn.ImageUrl = "/Content/ckdelete.png";
}
}
再一次,真的很简单。但请注意我们如何使用数据表的行状态(是否已删除)。
这还切换了删除按钮的图像。
因此,我们不必关心、担心或在网格中存储/保存状态。
所以,如果我点击几行删除,我现在得到这个:
到目前为止 - 很少的代码!!!
好的,现在是最后一部分。整体删除选定的按钮。好吧,因为这很危险 - 请注意我是如何在 OnClientClick 事件中添加“确认删除”的。如果您点击取消,那么服务器端事件当然不会运行。
但是,正如我们在持久化表格后所指出的那样?然后我们可以将删除的表直接发送回服务器而无需循环。因此删除代码如下所示:
protected void cmdDeleteAll_Click(object sender, EventArgs e)
{
// send updates (deletes) back to database.
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from tblHotels WHERE ID = 0",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daUpdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder daUpdateBuild = new SqlCommandBuilder(daUpdate);
daUpdate.Update(rstTable);
}
LoadGrid(); // refesh display
}
因此,请注意从数据库中更新(删除)是多么容易。如果你仔细看,我使用了那个网格的文本框——而不是标签。原因当然是如果用户在网格中使用选项卡(和编辑 - 非常像 excel),那么我可以用几行额外的代码将这些更改发送回数据库。事实上,上面的删除按钮代码在这里是 100% 相同的(它将与上面的代码一起发送表更改。所以,如果我们添加行,编辑行,那么上面并不是真正的删除命令,但实际上是我们的保存编辑/删除/添加命令!