在 VB 4.8 中编写网页。GridView 具有参数,这些参数指向 DetailsView 中的新数据字段

Writing a WebPage in VB 4.8. A GridView has parameters, which outlet to new Data Fields in a DetailsView

提问人:Ian Burton 提问时间:11/4/2022 最后编辑:Joel CoehoornIan Burton 更新时间:11/5/2022 访问量:69

问:

网页是为 Sales 设置的,我需要重新组织我得到的 ID 索引(在 GridView 中) 我选择了一个使用脚本化 DataTable 来填充 DetailsView 的过程。

Sub SortOrder_Item(ByVal Sender As Object, ByVal e As GridViewCommandEventArgs) Handles SortOrder.RowCommand
    Dim workTable As New System.Data.DataTable
            
    Dim DTabRow As System.Data.DataRow = workTable.NewRow

    Dim index As Integer = Convert.ToInt32(e.CommandArgument)           

    Dim Din As GridViewRow = SortOrder.Rows(index)
    if e.CommandName = "Add" Then
    Dim workCol As System.Data.DataColumn = workTable.Columns.Add("ID", Type.GetType("System.Int32"))
        workCol.AllowDBNull = false
        workCol.Unique = false
        Dim _Item_Name As String = Server.HTMLDecode(Din.Cells(1).Text)
        Dim _Curr_Price As Int32 = Server.HTMLDecode(Din.Cells(4).Text)
        Dim _REFNo As String = Server.HTMLDecode(Din.Cells(5).Text)
        Dim Dout As Int32 = index +1

        workCol = New System.Data.DataColumn()
        workCol.DataType = System.Type.GetType("System.String") 
        workCol.AllowDBNull = True
        workCol.Caption = ""
        workCol.ColumnName = "ItemName" & Dout 
        workCol.DefaultValue = ""
        workTable.Columns.Add(workCol)

        workCol = New System.Data.DataColumn()
        workCol.DataType = System.Type.GetType("System.Double") 
        workCol.AllowDBNull = True 
        workCol.Caption = ""
        workCol.ColumnName = "Curr_Price" & Dout
        workCol.DefaultValue = 0
        workTable.Columns.Add(workCol)
                        
        workCol = New System.Data.DataColumn()
            workCol.DataType = System.Type.GetType("System.String") 
            workCol.AllowDBNull = True 
            workCol.Caption = ""
            workCol.ColumnName = "REFNo" & Dout
            workCol.DefaultValue = ""
            workTable.Columns.Add(workCol)
        
        workCol = New System.Data.DataColumn()
            DTabRow("ID") = Dout
            DTabRow("ItemName" & Dout) = _Item_Name
            DTabRow("Curr_Price" & Dout) = _Curr_Price
            DTabRow("REFNo" & Dout) = _REFNo
        
            workTable.Rows.Add(DTabRow)
            DetailInsert.DataSource = workTable
            DetailInsert.DataBind()
            SortOrder.Enabled = False
        Go_NET.Visible = True
        else
            Go_NET.Visible = False
        end if
End Sub

            
  Sub CustomerDetailsView_ItemUpdating(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs)


  End Sub

  Sub CustomerDetailsView_ModeChanging(ByVal sender As Object, ByVal e As DetailsViewModeEventArgs)
  
    If e.CancelingEdit Then
      
      ' The user canceled the update operation.
      ' Clear the error message label.
      MesX1.Text = ""
    End If
    
  End Sub

因此,“编辑命令”不起作用,并且不会显示(更新/取消)控件。 如果我尝试直接将 DataSourceID 分配给我的 DetailsView 提交表单,我确信它可以工作,但整个数据库需要组织其索引。

asp.net vb.net GridView 数据表 详细信息视图

评论


答:

0赞 Albert D. Kallal 11/5/2022 #1

哎呀,你填写了 GV,那么为什么不直接获取该行的 pk ID,然后从数据库中重新提取那一行呢?

出于所有实际目的,它肯定不会真正增加服务器负载以重新拉取该记录。但是,虽然这不是性能问题,但它肯定会为您节省大量手动编码。

因此,我建议您不要尝试“手动编码”从 GV 创建一行。你只需要编写所有这些代码,但是如果你添加或更改列,你就会立即回到手工编码的一行数据。更糟糕的是,这样的代码真的不能被重用到其他页面。

我建议您简单地重新提取数据并获得一个漂亮的工作行。

随着时间的推移,我建议您构建一个“帮助程序”例程,该例程“自动”将一行中的列放入窗体上的控件中。这样一来,您就不必每次都手动编写控件加载代码。

然后编写一个例程来执行相反的操作(将控件中的值取回数据行)。然后再有一个例程将该行写出到数据库中。

有了这 3 个简单的例程,您现在可以将该代码用于所有表单和所有工作(而不是一遍又一遍地重写相当于相同代码的内容)。

你“可以”使用详细信息的视图,但你仍然必须输入 eval(“some column name”)。因此,不妨在 vb 中输入该代码 - 它的工作量大致相同。

因此,我建议采用以下方法:

我们的网格视图,并放入平面简常规编辑按钮(不要打扰 GridView 事件模型 - 它对于您开始使用自定义代码的非常即时的编辑来说并不是那么好)。

如前所述,详细信息视图也无济于事。 (因为我们不尝试使用内置向导,而且它们不是那么灵活)。

所以,我们的网格视图:

<div id="MyGridArea" runat="server">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
        DataKeyNames="ID"
        CssClass="table table-hover" Width="60em" GridLines="None"
        ShowHeaderWhenEmpty="true">
        <Columns>
            <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
            <asp:BoundField DataField="LastName" HeaderText="LastName" />
            <asp:BoundField DataField="City" HeaderText="City" />
            <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
            <asp:BoundField DataField="Description" HeaderText="Description" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn myshadow"
                        OnClick="cmdEdit_Click" />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</div>

请注意,我们该网格中既不公开也不包含 pk“ID”。我们设置/使用数据键设置(一个非常好的功能,从那时起我们不必尝试“隐藏”pk行,更好的是它是安全的 - 并且100%为我们管理服务器端)。

好的,现在我们加载网格的代码可以是这样的:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then
        LoadGrid()
    End If

End Sub

Sub LoadGrid()
    Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"

    GridView1.DataSource = Myrst(strSQL)
    GridView1.DataBind()

End Sub

我们现在有/看到这个:

enter image description here

好的,现在是我们的编辑按钮。

该标记是这样的:

            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn myshadow"
                        OnClick="cmdEdit_Click" />
                </ItemTemplate>
            </asp:TemplateField>

但请注意上面非常接近。请注意单击事件!!

但是,我们不能只双击该按钮来创建点击事件,因为它嵌套在 GV 中。那么这个巨大的好提示?

在标记中添加单击事件,然后键入

OnClick=

点击“=”的那一刻,然后注意关闭,你会看到一个弹出窗口来添加点击事件,如下所示:

enter image description here

因此,我们选择创建新事件。似乎没有发生太多事情,我们的按钮标记变成了这样:

<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn myshadow"
   OnClick="cmdEdit_Click" />

现在,如果我们切换到代码隐藏,我们会为该按钮单击一个按钮 - 但一个在 GV 内部。

因此,我们的按钮需要:

Get the current row id, and the row PK for the database row

We then transfer that data to our "div area", and then hide the GV,
display the "edit div".

以上是“不错的”,因为现在我们再次编写平面简简单标记,我们的取消、保存甚至删除按钮也是平面简代码。

因此,现在我们唯一需要的部分是我们的“编辑 div”区域。如前所述,我在这里没有看到太多使用详细信息视图的方式。您可以使用详细信息视图,但我认为它根本没有多大帮助。

好的,所以我们的编辑 div 如下所示:

(只需在“div”中用控件、复选框等平面简标记即可编辑一行)。

    <div id="EditRecord" runat="server" style="float: left; display: none" >

        <br />
        <div style="float: left" class="iForm">

            <label>HotelName</label>
            <asp:TextBox ID="txtHotel" runat="server" Width="280">
            </asp:TextBox>
            <br />
            <label>First Name</label>
            <asp:TextBox ID="tFN" runat="server" Width="140"></asp:TextBox>
            <br />
            <label>Last Name</label>
            <asp:TextBox ID="tLN" runat="server" Width="140"></asp:TextBox>
            <br />

            <label>City</label>
            <asp:TextBox ID="tCity" runat="server" Width="140"></asp:TextBox>

            <br />
            <label>Province</label><asp:TextBox ID="tProvince" runat="server" Width="75"></asp:TextBox>
        </div>

        <div style="float: left; margin-left: 20px" class="iForm">
            <div style="float: left">
                <label>Description</label>
                <br />
                <asp:TextBox ID="txtNotes" runat="server" Width="260px" TextMode="MultiLine"
                    Height="100px" ></asp:TextBox>
            </div>

            <div style="float: left; margin-left: 14px">
                <label>Hotel Options</label>
                <br />
                <asp:CheckBox ID="chkSmoking" runat="server" Text="Smoking" />
                <br />
                <asp:CheckBox ID="chkBalcony" runat="server" Text="Balcony" />
                <br />
                <asp:CheckBox ID="chkBags" runat="server" Text="Has Baggage" />
                <br />
            </div>

            <div style="clear: both">
            </div>

            <asp:CheckBox ID="chkActive" Text=" Active"
                runat="server" TextAlign="Right" Width="171px" />

        </div>
        <div style="clear: both"></div>
        <hr />

        <button id="cmdSave" runat="server" class="btn myshadow" type="button"
            onserverclick="cmdSave_ServerClick" >
            <span aria-hidden="true" class="glyphicon glyphicon-floppy-saved">Save</span>
        </button>

        <button id="cmdCancel" runat="server" class="btn myshadow" style="margin-left: 15px"
            type="button"
            onserverclick="cmdCancel_ServerClick" >
            <span aria-hidden="true" class="glyphicon glyphicon-arrow-left">Back/Cancel</span>
        </button>

        <button id="cmdDelete" runat="server" class="btn myshadow" style="margin-left: 15px"
            type="button"
            onserverclick="cmdDelete_ServerClick"
            onclick="if (!confirm('Delete this record?')) {return false};">
            <span aria-hidden="true" class="glyphicon glyphicon-trash">Delete</span>
        </button>
        <br />
        <br />
    </div>

</div>

仅供参考:

我在上面使用了html“按钮”。我本可以使用飞机简 asp.net 按钮,但我想要看起来很可爱的引导图标。我应该指出,在 bootstrap 4 之后,他们删除了 bootstap 图标的包含,但如果您愿意,如果您在使用 html“按钮”时遇到任何问题,请为这 3 个按钮使用 plane jane asp.net 按钮。我确实为这些按钮使用了 plane jane vb 代码,并注意我如何使用 onserverclick - 只是标记中的语法略有不同,但隐藏代码实际上与典型页面上的任何按钮单击代码相同。

好的,现在我们需要编辑按钮代码。

因此,这就是我们现在必须输入这些控件的地方。(如前所述,对于将来,我们可以编写一个例程,为任何标记一遍又一遍地执行此操作,但现在,婴儿步骤,只是一些婴儿步骤)。

因此,我们在编辑按钮上有此代码。

Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)

    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer

    Debug.Print("Row index click = " & gRow.RowIndex)

    ' get data base key
    Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
    Dim strSQL As String = "SELECT * FROM tblHotelsA WHERE ID = " & intPK

    Dim rstData As DataTable = Myrst(strSQL)
    ' load up our edit div area

    With rstData.Rows(0)

        txtHotel.Text = .Item("HotelName")
        tFN.Text = .Item("FirstName")
        tLN.Text = .Item("LastName")
        tCity.Text = .Item("City")
        tProvince.Text = .Item("Province")
        txtNotes.Text = .Item("Description")
        chkActive.Checked = .Item("Active")
        chkBalcony.Checked = .Item("Balcony")
        chkSmoking.Checked = .Item("Smoking")
    End With

    ViewState("PK") = intPK     ' same our PK for later
    ShowGrid(False)         ' hide GV, show edit area

End Sub

所以,真的,在标记中加入一堆 eval(“列名”),或者按照上面的顺序在文本框中输入 = 你付出的努力大致相同。

所以,实际上,现在我们只需要一个保存按钮来将数据写回表中。

该代码实际上与编辑按钮加载代码相反。

因此,此代码可以解决问题:

Protected Sub cmdSave_ServerClick(sender As Object, e As EventArgs)

    Dim intPK As Integer = ViewState("PK")
    Dim strSQL As String = "SELECT * FROM tblHotelsA WHERE ID = " & intPK

    Using conn = New SqlConnection(My.Settings.TEST4)
        Using cmdSQL = New SqlCommand(strSQL, conn)
            conn.Open()
            Dim da As New SqlDataAdapter(cmdSQL)
            Dim daU As New SqlCommandBuilder(da)

            Dim rstData As New DataTable
            rstData.Load(cmdSQL.ExecuteReader)

            With rstData.Rows(0)

                .Item("HotelName") = txtHotel.Text
                .Item("FirstName") = tFN.Text
                .Item("LastName") = tLN.Text
                .Item("City") = tCity.Text
                .Item("Province") = tProvince.Text
                .Item("Description") = txtNotes.Text
                .Item("Active") = chkActive.Checked
                .Item("Balcony") = chkBalcony.Checked
                .Item("Smoking") = chkSmoking.Checked
            End With

            da.Update(rstData)

        End Using
    End Using

    LoadGrid()   ' refrsh grid to show any new edits

    ShowGrid(True)

End Sub

所以,这在很大程度上产生了这样的效果:

enter image description here

所以,它不是很多代码,但我认为更重要的是所有的代码都是相当平面的简 - 没什么花哨的。

我使用的另一个“辅助例程”就是这个,它只是为给定的 SQL 查询返回一个表:

Public Function Myrst(strSQL As String) As DataTable

    Dim rstData As New DataTable
    Using mycon As New SqlConnection(My.Settings.TEST4)

        Using cmdSQL As New SqlCommand(strSQL, mycon)
            mycon.Open()
            rstData.Load(cmdSQL.ExecuteReader)
        End Using

    End Using

    Return rstData

End Function

仔细记下我如何使用简单的按钮单击来获取当前的 gv 行索引和 PK。该代码适用于转发器、列表视图、网格视图等,它允许您省去内置的网格/列表视图/转发器事件,并使用简单的按钮单击。

评论

0赞 Ian Burton 3/8/2023
谢谢你,阿尔伯特。但是你把我们带到哪里让我感到困惑。解决方案是让我为每个用户读取并重新插入多个 (ItemName),以便将其视为购买项目列表。需要包含“ID”。
0赞 Albert D. Kallal 3/9/2023
好吧,我们正在处理 2 个问题。第一个问题和目标是“解决”一行点击。获取该行的 PK。下一步可能是遛狗,插入多行,或打电话给妈妈。这里的关键要点是如何解决一行点击问题,接下来会发生什么,例如可能插入多行是这里的第二步和目标。但是,可以这么说。在你点击一行之后,它不清楚,如果那行点击是说将一行添加到其他表格或显示列表,但这并不重要。