如何编辑 SQL 数据库中网格视图中显示的数据
How to edit the data shown in a grid view from a SQL database
我使用网格视图创建了一个搜索功能,该程序读取用户输入并基于它 returns 从数据库中匹配的数据,但是它 returns 整行,其中包括 2 个我不想显示的 ID 列。听起来很简单,但我似乎找不到任何有关如何执行此操作的教程。
此外,第二列 IdCargo
(IdProfession,英文),我想翻译此数据,例如,如果应该出现特定 ID,我想改为显示职业所述员工。我还想显示名称为“Cargo”而不是“IdCargo”的列,而不是“CargaHoraria”我想显示“Carga Horaria”。
如果有人知道使用 GridView 和 SQL 的任何类型的指南或教程,那对未来的研究也将非常有帮助。
太好了。好的,我们不必太担心搜索部分 - 我假设您输入一些带有参数的搜索,结果是数据 table.
现在,我强烈建议您考虑使用列表视图代替网格视图。
至于控制哪些列?好吧,您可以为每一列设置模板。 (这就是我建议列表视图的原因 - 它的标记较少)。
但是,我没有太多的列 - 所以 GV 是“好的”,但是如果你想要更多的列,更多的自定义布局 - 那么 LV 将是 LESS 标记。
LV 的另一个真正大的优势是,您可以让它为您编写标记。
不管怎样,好的,这是我们的GV
非常重要:
每行都有一个 PK 主键(“ID”)。而我们当然不想展示或显示那个 PK ID,但众所周知,PK 是任何数据系统的命脉。因此,GV 中有一个非常酷的功能 - 称为 DataKeys。它允许您 use/have/play PK 行 ID,但您永远不必在 GV 中公开或显示它。 (所以不仅从 UI 的角度来看很好,从安全的角度来看也非常好)。
那么,假设我们有这样的 GV 布局:
<div style="width:40%;padding:25px">
<style> .borderhide input {border:none}</style>
<asp:GridView ID="GVPeople" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" cssclass="table borderhide">
<Columns>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:TextBox ID="FirstName" runat="server" Text='<%# Eval("FirstName") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Name">
<ItemTemplate>
<asp:TextBox ID="LastName" runat="server" Text='<%# Eval("LastName") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City">
<ItemTemplate>
<asp:TextBox ID="City" runat="server" Text='<%# Eval("City") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="Active" runat="server"
Checked='<%# Eval("Active") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Hotel ID">
<ItemTemplate>
<asp:TextBox ID="Hotel_ID" runat="server" Text='<%# Eval("Hotel_ID") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
我们会感觉到这个带有数据的 GV - 存在更多的列 - 但我们不在乎。
所以,到目前为止我的代码是这样的:
Dim rstData As New DataTable
Dim rstHotels As New DataTable ' for combo box
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
ViewState("rstData") = rstData
Else
rstData = ViewState("rstData")
End If
End Sub
Sub LoadGrid()
rstHotels = MyRst("SELECT ID, HotelName from tblHotels ORDER BY HotelName")
rstData = MyRst("SELECT * from People Order by FirstName")
GVPeople.DataSource = rstData
GVPeople.DataBind()
End Sub
现在我们有了这个:
好的,所以你的问题的一部分是我们显然不想显示 Hotel_id,而是想将其翻译成描述。当然,如果我们要允许编辑,那么让我们将 Hotel_ID 转换为组合框(下拉列表)。和near most/all组合框一样,我们会存储酒店的PK id,但当然会显示酒店名称以方便使用。
因此,代替 hotel_id,我们将标记更改为:
<asp:TemplateField HeaderText="Hotel ID">
<ItemTemplate>
<asp:DropDownList ID="cboHotel" runat="server"
DataTextField="HotelName"
DataValueField="ID">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
好的,现在我们必须填充 + 设置组合框。我们有两个任务:
用数据源填充组合框
将组合框设置为每个 gv 行的当前选择。
为此,我们将使用 GV 行数据绑定事件。
因此,我们填写组合的代码如下所示:
所以我们有这个代码:
Protected Sub GVPeople_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GVPeople.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
' get full row of data bind - all columns
Dim gData As DataRowView = e.Row.DataItem ' NOT A GRID VIEW ROW!!!!!
' get combo box
Dim cboHotels As DropDownList = e.Row.FindControl("cboHotel")
' setup cbo data source
cboHotels.DataSource = rstHotels
cboHotels.DataBind()
cboHotels.Items.Insert(0, New ListItem("", "")) ' add blank (no choice)
If IsDBNull(gData("Hotel_id")) = False Then
cboHotels.SelectedValue = gData("Hotel_ID").ToString
End If
End If
End Sub
所以,现在我们的结果是这样的:
好的,这样就可以处理您的 questions/issues.
接下来是编辑 - 这真的很酷,也很容易。
好吧,如果你仔细看,我“隐藏”了文本框的边框,但你现在发现你可以像 excel 一样四处移动。一个很好的免费蜜蜂是当文本框有焦点时,它们会显示!!
因此,让我们将我们的按钮放在网格下方以保存编辑。当我四处张望时它看起来像这样:
非常像魔术 - 您现在可以使用 Tab 键 - 几乎像 Excel。您可以选择组合框值。
在上面,我们在 GV 下方放置了一个简单的按钮,如下所示:
</asp:GridView>
<asp:Button ID="cmdSave" runat="server" Text="Save Edits" CssClass="btn" />
好的,现在是保存数据按钮。
我们将编写一个辅助例程。将此代码拆分为两个例程的原因有很多。那么第一个套路呢?
它会将网格值发送回我们的 table。如果仔细观察,我将 GV table 数据源保留为 rstData。
因此此例程将网格发送回 table。
Sub GridToTable()
' pull GV rows back to table.
For Each gRow As GridViewRow In GVPeople.Rows
' Get database PK value
Dim PK As Integer = GVPeople.DataKeys(gRow.RowIndex).Item("ID")
Dim OneDataRow As DataRow = rstData.Select("id = " & PK)(0)
OneDataRow.Item("FirstName") = CType(gRow.FindControl("FirstName"), TextBox).Text
OneDataRow.Item("LastName") = CType(gRow.FindControl("LastName"), TextBox).Text
OneDataRow.Item("City") = CType(gRow.FindControl("City"), TextBox).Text
OneDataRow.Item("Active") = CType(gRow.FindControl("Active"), CheckBox).Checked
' combo box
Dim cboHotel As DropDownList = gRow.FindControl("cboHotel")
If cboHotel.Text = "" Then
OneDataRow("Hotel_ID") = DBNull.Value
Else
OneDataRow("Hotel_ID") = cboHotel.SelectedItem.Value
End If
Next
End Sub
好的,现在我们要做的就是发送 rstData table(并得到这个:这将处理新行,或编辑!!!!)。
所以,现在我们的保存按钮代码如下所示:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
GridToTable()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn)
Dim da As New SqlDataAdapter(cmdSQL)
Dim daC As New SqlCommandBuilder(da)
conn.Open()
da.Update(rstData)
End Using
End Using
End Sub
所以请注意我们是如何将整个网格发送回数据库的,所有的更改都是一次性完成的。
最后但同样重要的是:
我使用了一个辅助例程来获取数据 table(一遍又一遍地快速输入那种代码变得非常快,所以我有了这个并且我将它设置为整个应用程序的全局:
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
rstData.TableName = strSQL
End Using
End Using
Return rstData
End Function
注意非常小心,我还将 sql 语句填充到 rst.Table 名称中。 Table 名称并没有真正使用过,但现在因为我坚持使用 SQL table?
那么其实这一行
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn)
变为:
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(rstData.TableName, conn)
这意味着if/when我说的是子母版,还是多个table的数据要在一个页面上编辑?我使用一个数据集(tables 的集合),并且有一个 routien 将所有 tables 和所有编辑在一个 shot/routine 中发送回数据库。我们没有超过一个 table 的数据要编辑,但这解释了为什么我将 SQL 语句推入数据 table “table” 名称,因为如您所见,那么我们甚至不必重新键入使用的 sql。
注意事项:
我使用的 sql 语句:
SELECT * from People WHERE ID = 0
不是 o 型。我用它来允许 sqlCommandBuilder 为我完成连接和创建 sql 插入和更新蒸汽的所有脏活。
我使用网格视图创建了一个搜索功能,该程序读取用户输入并基于它 returns 从数据库中匹配的数据,但是它 returns 整行,其中包括 2 个我不想显示的 ID 列。听起来很简单,但我似乎找不到任何有关如何执行此操作的教程。
此外,第二列 IdCargo
(IdProfession,英文),我想翻译此数据,例如,如果应该出现特定 ID,我想改为显示职业所述员工。我还想显示名称为“Cargo”而不是“IdCargo”的列,而不是“CargaHoraria”我想显示“Carga Horaria”。
如果有人知道使用 GridView 和 SQL 的任何类型的指南或教程,那对未来的研究也将非常有帮助。
太好了。好的,我们不必太担心搜索部分 - 我假设您输入一些带有参数的搜索,结果是数据 table.
现在,我强烈建议您考虑使用列表视图代替网格视图。
至于控制哪些列?好吧,您可以为每一列设置模板。 (这就是我建议列表视图的原因 - 它的标记较少)。
但是,我没有太多的列 - 所以 GV 是“好的”,但是如果你想要更多的列,更多的自定义布局 - 那么 LV 将是 LESS 标记。
LV 的另一个真正大的优势是,您可以让它为您编写标记。
不管怎样,好的,这是我们的GV
非常重要: 每行都有一个 PK 主键(“ID”)。而我们当然不想展示或显示那个 PK ID,但众所周知,PK 是任何数据系统的命脉。因此,GV 中有一个非常酷的功能 - 称为 DataKeys。它允许您 use/have/play PK 行 ID,但您永远不必在 GV 中公开或显示它。 (所以不仅从 UI 的角度来看很好,从安全的角度来看也非常好)。
那么,假设我们有这样的 GV 布局:
<div style="width:40%;padding:25px">
<style> .borderhide input {border:none}</style>
<asp:GridView ID="GVPeople" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" cssclass="table borderhide">
<Columns>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:TextBox ID="FirstName" runat="server" Text='<%# Eval("FirstName") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Last Name">
<ItemTemplate>
<asp:TextBox ID="LastName" runat="server" Text='<%# Eval("LastName") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="City">
<ItemTemplate>
<asp:TextBox ID="City" runat="server" Text='<%# Eval("City") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="Active" runat="server"
Checked='<%# Eval("Active") %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Hotel ID">
<ItemTemplate>
<asp:TextBox ID="Hotel_ID" runat="server" Text='<%# Eval("Hotel_ID") %>' ></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
我们会感觉到这个带有数据的 GV - 存在更多的列 - 但我们不在乎。
所以,到目前为止我的代码是这样的:
Dim rstData As New DataTable
Dim rstHotels As New DataTable ' for combo box
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
ViewState("rstData") = rstData
Else
rstData = ViewState("rstData")
End If
End Sub
Sub LoadGrid()
rstHotels = MyRst("SELECT ID, HotelName from tblHotels ORDER BY HotelName")
rstData = MyRst("SELECT * from People Order by FirstName")
GVPeople.DataSource = rstData
GVPeople.DataBind()
End Sub
现在我们有了这个:
好的,所以你的问题的一部分是我们显然不想显示 Hotel_id,而是想将其翻译成描述。当然,如果我们要允许编辑,那么让我们将 Hotel_ID 转换为组合框(下拉列表)。和near most/all组合框一样,我们会存储酒店的PK id,但当然会显示酒店名称以方便使用。
因此,代替 hotel_id,我们将标记更改为:
<asp:TemplateField HeaderText="Hotel ID">
<ItemTemplate>
<asp:DropDownList ID="cboHotel" runat="server"
DataTextField="HotelName"
DataValueField="ID">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
好的,现在我们必须填充 + 设置组合框。我们有两个任务:
用数据源填充组合框
将组合框设置为每个 gv 行的当前选择。
为此,我们将使用 GV 行数据绑定事件。
因此,我们填写组合的代码如下所示:
所以我们有这个代码:
Protected Sub GVPeople_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GVPeople.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
' get full row of data bind - all columns
Dim gData As DataRowView = e.Row.DataItem ' NOT A GRID VIEW ROW!!!!!
' get combo box
Dim cboHotels As DropDownList = e.Row.FindControl("cboHotel")
' setup cbo data source
cboHotels.DataSource = rstHotels
cboHotels.DataBind()
cboHotels.Items.Insert(0, New ListItem("", "")) ' add blank (no choice)
If IsDBNull(gData("Hotel_id")) = False Then
cboHotels.SelectedValue = gData("Hotel_ID").ToString
End If
End If
End Sub
所以,现在我们的结果是这样的:
好的,这样就可以处理您的 questions/issues.
接下来是编辑 - 这真的很酷,也很容易。
好吧,如果你仔细看,我“隐藏”了文本框的边框,但你现在发现你可以像 excel 一样四处移动。一个很好的免费蜜蜂是当文本框有焦点时,它们会显示!!
因此,让我们将我们的按钮放在网格下方以保存编辑。当我四处张望时它看起来像这样:
非常像魔术 - 您现在可以使用 Tab 键 - 几乎像 Excel。您可以选择组合框值。
在上面,我们在 GV 下方放置了一个简单的按钮,如下所示:
</asp:GridView>
<asp:Button ID="cmdSave" runat="server" Text="Save Edits" CssClass="btn" />
好的,现在是保存数据按钮。
我们将编写一个辅助例程。将此代码拆分为两个例程的原因有很多。那么第一个套路呢?
它会将网格值发送回我们的 table。如果仔细观察,我将 GV table 数据源保留为 rstData。
因此此例程将网格发送回 table。
Sub GridToTable()
' pull GV rows back to table.
For Each gRow As GridViewRow In GVPeople.Rows
' Get database PK value
Dim PK As Integer = GVPeople.DataKeys(gRow.RowIndex).Item("ID")
Dim OneDataRow As DataRow = rstData.Select("id = " & PK)(0)
OneDataRow.Item("FirstName") = CType(gRow.FindControl("FirstName"), TextBox).Text
OneDataRow.Item("LastName") = CType(gRow.FindControl("LastName"), TextBox).Text
OneDataRow.Item("City") = CType(gRow.FindControl("City"), TextBox).Text
OneDataRow.Item("Active") = CType(gRow.FindControl("Active"), CheckBox).Checked
' combo box
Dim cboHotel As DropDownList = gRow.FindControl("cboHotel")
If cboHotel.Text = "" Then
OneDataRow("Hotel_ID") = DBNull.Value
Else
OneDataRow("Hotel_ID") = cboHotel.SelectedItem.Value
End If
Next
End Sub
好的,现在我们要做的就是发送 rstData table(并得到这个:这将处理新行,或编辑!!!!)。
所以,现在我们的保存按钮代码如下所示:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
GridToTable()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn)
Dim da As New SqlDataAdapter(cmdSQL)
Dim daC As New SqlCommandBuilder(da)
conn.Open()
da.Update(rstData)
End Using
End Using
End Sub
所以请注意我们是如何将整个网格发送回数据库的,所有的更改都是一次性完成的。
最后但同样重要的是:
我使用了一个辅助例程来获取数据 table(一遍又一遍地快速输入那种代码变得非常快,所以我有了这个并且我将它设置为整个应用程序的全局:
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
rstData.TableName = strSQL
End Using
End Using
Return rstData
End Function
注意非常小心,我还将 sql 语句填充到 rst.Table 名称中。 Table 名称并没有真正使用过,但现在因为我坚持使用 SQL table?
那么其实这一行
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * from People where ID = 0", conn)
变为:
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(rstData.TableName, conn)
这意味着if/when我说的是子母版,还是多个table的数据要在一个页面上编辑?我使用一个数据集(tables 的集合),并且有一个 routien 将所有 tables 和所有编辑在一个 shot/routine 中发送回数据库。我们没有超过一个 table 的数据要编辑,但这解释了为什么我将 SQL 语句推入数据 table “table” 名称,因为如您所见,那么我们甚至不必重新键入使用的 sql。
注意事项: 我使用的 sql 语句:
SELECT * from People WHERE ID = 0
不是 o 型。我用它来允许 sqlCommandBuilder 为我完成连接和创建 sql 插入和更新蒸汽的所有脏活。