如何从 SQL 数据库编辑网格视图中显示的数据

Posted

技术标签:

【中文标题】如何从 SQL 数据库编辑网格视图中显示的数据【英文标题】:How to edit the data shown in a grid view from a SQL database 【发布时间】:2022-01-05 07:22:31 【问题描述】:

我使用网格视图创建了一个搜索功能,程序读取用户输入并基于它返回与数据库匹配的数据,但是它返回整行,其中包括 2 个我没有的 ID 列想展示。听起来很简单,但我似乎找不到任何关于如何做到这一点的教程。

另外,第二列IdCargo(IdProfession,英文),我想翻译这些数据,例如,如果应该出现特定的 ID,我想显示该员工的职业。我还想用“Cargo”名称而不是“IdCargo”显示列,也想显示“Carga Horaria”而不是“CargaHoraria”。

如果有人知道任何使用 GridViews 和 SQL 的指南或教程,那对未来的研究也非常有帮助。

【问题讨论】:

【参考方案1】:

太好了。好的,我们不必太担心搜索部分——我假设你输入了一些搜索,带有参数,结果是一个数据表。

现在,我强烈建议您考虑使用列表视图代替网格视图。

至于控制哪些列?好吧,您可以对每一列进行模板化。 (这就是为什么我建议使用列表视图 - 它的标记更少)。

但是,我没有太多的列 - 所以 GV 是“好的”,但是如果你想要更多的列,更多的自定义布局 - 那么 LV 将是 LESS 标记。

LV 的另一个真正大的优势是你可以让它为你编写标记。

不管怎样,好吧,这是我们的 GV。

非常重要: 每行都有一个 PK 主键(“ID”)。我们当然不想显示或显示那个 PK ID,但众所周知,PK 是任何数据系统的命脉。因此,GV 中有一个非常酷的功能——称为 DataKeys。它允许您使用/拥有/播放 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 转换为组合框(下拉列表)。和大多数/所有组合框一样,我们将存储酒店的 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

所以,现在我们的结果是这样的:

好的,这样就可以解决您的一个问题/问题。

接下来是编辑 - 这真的很酷,也很简单。

好的,如果您仔细观察,我会“隐藏”文本框的边框,但您现在发现您可以像 Excel 一样使用 Tab 键。一个不错的免费蜜蜂是当文本框有焦点时,它们会显示!!

因此,让我们将我们的按钮放在网格下方以保存编辑。当我点击时它看起来像这样:

很像魔术 - 您现在可以使用标签 - 几乎就像 Excel。并且您可以选择组合框的值。

在上面,我们在 GV 下方放置了一个简单的按钮,如下所示:

        </asp:GridView>
        <asp:Button ID="cmdSave" runat="server" Text="Save Edits" CssClass="btn" />

好的,现在是保存数据按钮。

我们将编写一个辅助例程。将此代码拆分为两个例程的原因有很多。那么第一个套路呢?

它将网格值发送回我们的表。如果仔细观察,我会将 GV 表数据源持久化为 rstData。

所以这个例程将网格发送回表格。

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 表(并得到这个:这将处理新行或编辑!!!!)。

所以,现在我们的保存按钮代码如下所示:

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

所以请注意我们如何将整个网格发送回数据库,以及一次拍摄中的所有更改。

最后但并非最不重要的一点:

我使用了一个辅助例程来获取一个数据表(一遍又一遍地键入那种代码变得非常快速,所以我有了这个并将其设置为对整个应用程序都是全局的:

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 名称中。表名并没有真正使用,但现在因为我为该表保留了 SQL?

那么其实就是这一行

    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)

这意味着如果/当我说要在页面上编辑子母版或多个数据表时?我使用一个数据集(表的集合),并有一个 routien 一次性将所有表和所有编辑发送回数据库。我们没有超过一个数据表要编辑,但这解释了为什么我将 SQL 语句推入数据表“表”名称,因为如您所见,我们甚至不必重新输入使用的sql。

请注意: 我使用的那个sql语句:

SELECT * from People WHERE ID = 0

不是类型-o。我用它来让 sqlCommandBuilder 为我完成所有繁琐的连接和创建 sql 插入和更新流的工作。

【讨论】:

没有比这更复杂的gridview了,它是一个非常基础的学校网站,而且我喜欢gridview看起来更好。此外,我最终找到了一篇关于网格视图的文章,因此我设法更改了列的名称,唯一我还没有弄清楚的是如何将 ID“翻译”成它们所代表的内容 好吧,看看我的编辑 - 这是星期六 - 吃披萨 - 但我将发布最后一点和小代码,以展示我们如何使用简单 + 简单的代码发回网格编辑。所以在 15 分钟左右,我会回来完成下一段代码。但是发布的代码显示了我如何将值转换为组合框 另外,请随时询问 c# 代码 - 对我来说没什么区别(但由于 vb 提供了大量的自动转换,VB 代码的工作量较小)。 好了,看最后一部分再更新。请注意,代码非常简单,只需一次将整个编辑表发送回数据库。

以上是关于如何从 SQL 数据库编辑网格视图中显示的数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode 5 中显示故事板视图/编辑的网格?

如何在数据网格视图中显示数据

如何从编辑器中排除不在数据源中的剑道网格字段?

如何在可缩放滚动视图中绘制可点击的网格对象,从远程 json 数据中获取数据?

如何在 SQL Server Management Studio 中编辑结果网格中的数据

Kendo UI Hierarchical datagrid - 如何从详细网格编辑器模板 MVVM 访问根视图模型