好的,有两种方法可以做到这一点,在这里你可以很容易地使用js。但是,让我们使用 100% 的服务器端代码。我认为坚持使用服务器端代码更容易。
下一个?实际上,当您计划编辑数据时,我建议使用列表视图代替网格视图。原因很简单——ListView 不需要那些“令人讨厌的”“项目模板”一遍又一遍地为您想要在该网格显示中删除/拥有的每个 asp.net 控件。现在公平地说,说 2-3 个控件 - 然后网格视图是可以的,但是更多,然后我真的发现列表视图开始在这里赢得很大的时间(不需要项目模板)。
listview的“诀窍”当然是在网页上设置一个数据源,让它生成标记,然后吹出(删除)除项目模板之外的所有模板。然后删除页面上的datasource1项,并从列表视图中删除datasource1设置。
但是,让我们使用网格视图 - 因此这将是一些“更混乱”的东西
所以,我们要填写网格 - 并说我们想要一个城市组合框 - 必须选中。让我们进行基本检查,说 LastName 也必须输入。
所以,我们有一个城市组合框(数据库驱动)。假设让我们在一个下拉列表中折腾酒店评级(1-5)——但这只有 5 个选择——所以我们有那个带有标记列表的下拉列表。 (所以两个组合示例来说明这是如何工作的)。
所以,假设我们有一个这样的网格,然后我们点击保存,我们会得到这个结果:
现在,我们当然会喜欢那个消息框区域。事实上,我们可以很容易地放入 jQuery.UI 并让右边那个可爱的 div 出现在一个对话框中(我们甚至可以从我们后面的服务器端代码触发那个框 + jQuery.UI 对话框显示 - 但让我们试试并保持简短 - 但我会喜欢那个错误消息区域)。
好的,首先是标记:
只是一个简单的网格,但由于那些“项目模板”而“有点混乱” - (如果你不明白这一点,我真的不喜欢那些模板的东西!!! - 使用列表视图你不需要它们!! - 只需为网格添加纯干净的 asp.net 控件)。无论如何:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
<asp:TemplateField HeaderText="HotelName" >
<ItemTemplate><asp:TextBox id="HotelName" runat="server" Text='<%# Eval("HotelName") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="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:DropDownList ID="cboCity" runat="server" DataTextField="City"
DataValueField = "City" Width="110px">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active">
<ItemTemplate><asp:CheckBox id="Active" runat="server" Checked = '<%# Eval("Active") %>' /></ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Rating">
<ItemTemplate>
<asp:DropDownList ID="cboRating" runat="server" SelectedValue = '<%# Eval("Rating") %>' >
<asp:ListItem Value="1">Poor</asp:ListItem>
<asp:ListItem Value="2">Just Ok</asp:ListItem>
<asp:ListItem Value="3">Ok</asp:ListItem>
<asp:ListItem Value="4">Good</asp:ListItem>
<asp:ListItem Value="5">Excellent</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div id="ErrorDialog" style="display:normal;float:left;padding-left:30px;width:20%" runat="server">
<asp:TextBox ID="txtErrors" runat="server" TextMode="MultiLine" Style="width:100%" Rows="20" ></asp:TextBox>
</div>
<div style="clear:both;padding-top:20px">
<asp:Button ID="cmdSave" runat="server" Text="Save" />
<asp:Button ID="cmdUnDo" runat="server" Text="UnDo" Style="margin-left:20px"/>
</div>
好的,现在开始了吗?哎呀,这大约是我一次发布的最大标记总数 - 超出上述范围,我们接近“不太好”的帖子领域。
好的,让我们看看加载这个网格的代码。我们有这个代码:
public class EditHotelsG : System.Web.UI.Page
{
private DataTable rstTable = new DataTable();
private DataTable rstCity = new DataTable();
protected void Page_Load(object sender, System.EventArgs e)
{
if (System.Web.UI.Page.IsPostBack == false)
{
ErrorDialog.Visible = false;
LoadGrid();
ViewState["rstTable"] = rstTable;
ViewState["rstCity"] = rstCity;
}
else
{
rstTable = ViewState["rstTable"];
rstCity = ViewState["rstCity"];
}
}
public void LoadGrid()
{
// load up our drop down list from database (city)
string strSQL;
strSQL = "SELECT City from tblCity Order by City";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
cmdSQL.Connection.Open();
rstCity.Load(cmdSQL.ExecuteReader);
// now load up main grid view
strSQL = "SELECT ID, FirstName, LastName, HotelName, City, Active, Rating from tblHotels ORDER BY HotelName";
cmdSQL.CommandText = strSQL;
rstTable.Load(cmdSQL.ExecuteReader);
GridView1.DataSource = rstTable;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
// set combo box data source
if (e.Row.RowType == DataControlRowType.DataRow)
{
// setup city drop down list
DropDownList cboDrop = e.Row.FindControl("cboCity");
cboDrop.DataSource = rstCity;
cboDrop.DataBind();
cboDrop.Items.Insert(0, new ListItem(string.Empty)); // add blank row
cboDrop.Text = rstTable.Rows(e.Row.RowIndex).Item("City").ToString;
}
}
}
好的,现在代码不多了。一个很好的部分是设置组合框。由于 cbo 框(下拉列表)是数据库驱动的,因此我们必须为每一行绑定 + 设置。因此,这花费了我们大量的编码时间。
但是请注意我们如何持久化数据库源(表)。我们这样做,因为我们想要使用 A LOT LESS 代码,所以一次更新整个数据库。通过持久化该表,然后我们
Transfer data from Grid to table
Save the table to database in one shot
因此,这减少了我们的编码工作量。
保存数据的代码,因此变成了这个 gem:
(并注意我们如何输入验证代码)。
protected void cmdSave_Click(object sender, EventArgs e)
{
// pull gride rows back to table.
bool bolDataOk = true;
txtErrors.Text = "";
foreach (GridViewRow rRow in GridView1.Rows)
{
int RecordPtr = rRow.RowIndex;
DataRow OneDataRow;
OneDataRow = rstTable.Rows(RecordPtr);
OneDataRow.Item("HotelName") = rRow.FindControl("HotelName") as TextBox.Text;
OneDataRow.Item("FirstName") = rRow.FindControl("FirstName") as TextBox.Text;
OneDataRow.Item("LastName") = rRow.FindControl("LastName") as TextBox.Text;
OneDataRow.Item("City") = rRow.FindControl("cboCity") as DropDownList.Text;
OneDataRow.Item("Active") = rRow.FindControl("Active") as CheckBox.Checked;
OneDataRow.Item("Rating") = rRow.FindControl("cboRating") as DropDownList.SelectedValue;
// check for missing City, or LastName
if (IsDBNull(OneDataRow("City")) | OneDataRow("City") == "")
{
bolDataOk = false;
if (txtErrors.Text != "")
txtErrors.Text += Constants.vbCrLf;
txtErrors.Text += "Missing City on row = " + (rRow.RowIndex + 1).ToString;
}
if (IsDBNull(OneDataRow("LastName")) | OneDataRow("LastName") == "")
{
bolDataOk = false;
if (txtErrors.Text != "")
txtErrors.Text += Constants.vbCrLf;
txtErrors.Text += "Missing lastName on row = " + (rRow.RowIndex + 1).ToString;
}
}
ErrorDialog.Visible = !(bolDataOk);
// now send table back to database with updates
if (bolDataOk)
{
string strSQL = "SELECT ID, FirstName, LastName, City, HotelName, Active, Rating from tblHotels WHERE ID = 0";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);
daupdate.Update(rstTable);
}
}
}
现在,再一次,上面的代码片段有点长 - 并且是 SO 的代码片段的最大大小。我可能会考虑将上面最后的代码分解为 2 个甚至 3 个例程。
但是,总而言之,上面展示了相当多的技巧和方法。
如前所述,我将发布您如何/可以使用客户端代码进行验证,但是通过一次数据库更新来保存整个网格的全部想法?好吧,我会将这个技巧与 listview、gridview 一起使用,即使我正在做客户端 js 验证?我仍然会使用上面的大部分设计模式。
还有撤消按钮?好吧,我从来没有完成那部分 - 但它只会调用与第一页加载相同的代码(回发 - 错误,您只需从数据库源重新绑定网格以获得撤消按钮。