簡體   English   中英

如何使用 VB.net 循環瀏覽網頁上的所有控件

[英]How to loop thru all controls on a web page using VB.net

我試圖想出一種方法來循環遍歷 aspx 頁面上的所有控件(文本框、復選框、下拉列表等)。 我嘗試將在線為 C# 提供的一些解決方案轉換為 VB,但沒有任何效果。

我用

for all c in me.controls
    id = c.id 
next 

循環,但沒有獲得頁面上的任何控件。 我也試過這個,結果相同:

Sub checkcontrol(ByRef Parent As Control)
    Dim c As Control
    Dim x As Integer = Parent.Controls.Count
    For Each c In Parent.Controls
        If c.GetType.ToString = "ASP.site_master" Then
            checkcontrol(c)
        ElseIf c.GetType() Is GetType(TextBox) Then
            'is it a Text Box?
            Dim t As TextBox = c
            Debug.Print("textBox " & c.ID)
        ElseIf c.GetType() Is GetType(DropDownList) Then
            'is it a dropdown list?
            Dim d As DropDownList = c
            Debug.Print("DropDown Box " & c.ID)
            '   d.ClearSelection()
        ElseIf c.GetType() Is GetType(CheckBox) Then
            Debug.Print("check Box " & c.ID)
        ElseIf c.GetType() Is GetType(RadioButton) Then
            Debug.Print("Radio Button " & c.ID)
        End If
    Next
End sub

我得到的第一個類型是“ASP.site_master”,因為該頁面鏈接到 Site Master。我在 Visual Studio 社區 2017 上並在調試模式下運行。

我究竟做錯了什么?

可以有更多層。 始終尋找子控件:

Sub checkcontrol(ByRef Parent As Control)   
    For Each c As Control In Parent.Controls       
        If c.GetType() Is GetType(TextBox) Then
            'is it a Text Box?
            Dim t As TextBox = c
            Debug.Print("textBox " & c.ID)
        ElseIf c.GetType() Is GetType(DropDownList) Then
            'is it a dropdown list?
            Dim d As DropDownList = c
            Debug.Print("DropDown Box " & c.ID)
            '   d.ClearSelection()
        ElseIf c.GetType() Is GetType(CheckBox) Then
            Debug.Print("check Box " & c.ID)
        ElseIf c.GetType() Is GetType(RadioButton) Then
            Debug.Print("Radio Button " & c.ID)
        End If

        If c.Controls.Count > 0 Then checkcontrol(c)
    Next
End Sub

為了娛樂:

Iterator Function AllControls(ByRef Parent As Control) As IEnumerable(Of Control)
    For Each c As Control In Parent.Controls       
        Yield c
        If c.Controls.Count > 0 Then
            For Eachchild As Control In AllControls(c)
               Yield child
            Next
        End If
    Next
End Sub

然后像這樣使用它:

For Each c As Control In AllControlls(Me)
    Debug.Print($"Type: {c.GetType()}{vbTab}ID: {c.Id}{vbTab}Name: {c.Name}")
Next

實際上,我非常嘗試編寫代碼來獲取數據表行,發送到網頁上的控件。 讓用戶編輯,然后將控件的值發送回數據庫。 來自 VBA、vb、vb.net 桌面,然后一遍又一遍地編寫這樣的代碼似乎是一種愚蠢的浪費時間。

所以,我寫了一個例程來循環控制。 但是,在給定的頁面上,我經常需要不止一個部分(一組值可能來自一個表,而另一部分來自另一個表)。

所以,我假設我想要使用的控件分組放在一個 div 中。

所以,假設我想編輯酒店信息。

而且我不想磨損我的鍵盤。

而且我不想每次要編輯記錄時都一遍又一遍地編寫相同的代碼?

好吧,我們建立了 2 個例程。

將數據行發送到網頁的例程 - (但是,我們使用“div”來控制哪些部分)。

將網頁發送回數據行的例程。

然后例程將數據行(數據表)發送回數據庫。

唯一的另一部分? 我們如何對控件進行數據綁定? 好吧,我們可以突然為每個控件添加任何舊標記。 所以,我只使用“f”,這意味着數據列名。

最終結果?

實際上,我們最終使用了一個“迷你”框架來編輯數據,這樣做時沒有雜亂的綁定表達式,也沒有雜亂的模板或任何東西。

只需簡單的代碼、簡單的標記,您現在就擁有了一個完整的 CRUD 系統。

例子:

簡單的網格視圖顯示一些酒店:

    <div id="MyGrid" runat="server" style="width:40%">
        <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="ID" CssClass="table">
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName"  />
                <asp:BoundField DataField="Description" HeaderText="Description"  />
                <asp:TemplateField HeaderText="Edit">
                    <ItemTemplate>
                        <asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn" OnClick="cmdEdit_Click" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        <br />
    </div>

好的,要加載的代碼:

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 cmdSQL As New SqlCommand("SELECT * FROM tblHotelsA ORDER BY HotelName")
    GHotels.DataSource = MyrstP(cmdSQL)
    GHotels.DataBind()

End Sub

我們現在有了這個:

在此處輸入圖像描述

到目前為止,沒有什么新鮮事——死的很簡單。 (別擔心,我稍后會分享幫助程序)。

好的,所以,在上面我們將一個平面 jane asp.net 按鈕放入網格視圖中(不要為 GV 的內置事件煩惱 - 它們更痛苦而不是幫助)。

現在,通常情況下,要給按鈕添加點擊,您只需雙擊這些按鈕,但由於 GV 內的按鈕(或任何控件)不允許這樣做?

然后你使用標記,輸入 onclick=""。 你得到/看到這個:

在此處輸入圖像描述

所以,選擇創建新事件。 現在,我們可以在 gridview 中使用一個簡單的點擊事件(這個技巧適用於所有控件 - 下拉菜單或其他)。 這個技巧拯救了我們的世界貧困,我們現在可以享受並使用 GV 的簡單標准按鈕單擊事件 - 沒有混亂的行命令和導致世界貧困的努力。

當我們點擊一​​行時,我們將:

隱藏 GV,顯示我們的 div 來編輯行。 使用我們方便的頁面循環控件例程(您當前的問題),並填寫 div。

所以,首先我們的 div 放在網格下方 - 這是我們的編輯 div。

說這個:

    <div id="EditRecord" runat="server" style="float:left;display: normal" clientidmode="Static"  >
        <style>
            .iForm label {display:inline-block;width:90px}
            .iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}                
            .iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}     
            .iForm input[type=checkbox] {margin-right:8px}
        </style>

        <div style="float:left" class="iForm">
                <label>HotelName</label><asp:TextBox ID="txtHotel" runat="server" f="HOtelName" width="280"></asp:TextBox> <br />
                <label>First Name</label><asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140"></asp:TextBox> <br />
                <label>Last Name</label><asp:TextBox ID="tLN" runat="server" f="LastName" Width="140"></asp:TextBox> <br />
                <label>City</label><asp:TextBox ID="tCity" runat="server" f="City" Width="140"></asp:TextBox> <br />
                <label>Province</label><asp:TextBox ID="tProvince" runat="server" f="Province" Width="75"></asp:TextBox> <br />
        </div>
        <div style="float:left;margin-left:20px" class="iForm">
            <label>Description</label> <br />
            <asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine" 
                Height="150px" f="Description" ></asp:TextBox> <br />
            <asp:CheckBox ID="chkActive" f="Active" Text=" Active" runat="server" TextAlign="Right" />
            <asp:CheckBox ID="chkBalcony" f="Balcony" Text=" Has Balcony" runat="server" TextAlign="Right" />
        </div>
        <div style="clear:both"></div>
        <button id="cmdSave" runat="server" class="btn" onserverclick="cmdSave_ServerClick" >
            <span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Save</span> 
        </button>

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

        <button id="cmdDelete" runat="server" class="btn" style="margin-left:15px">
            <span aria-hidden="true" class="glyphicon glyphicon-trash"> Delete</span>
        </button>
   </div>

現在,在上面,我決定只使用一個 html 按鈕,原因是 EASE 可以在其中向按鈕添加圖標。 (但是,也可以使用plane jane asp.net 按鈕)。

除了我們添加了“f”之外,請注意上面的特別之處。 那是數據庫列映射!!! 真的很簡單,而且比使用中繼器之類的數據綁定對象少了無數倍的工作量。

所以,現在按鈕代碼點擊:

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

    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer
    Dim pkID = GHotels.DataKeys(gRow.RowIndex).Item("ID")

    Dim cmdSQL As New SqlCommand("SELECT * from tblHotelsA where ID = @ID")
    cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = pkID
    Dim rstData As DataTable = MyrstP(cmdSQL)

    Call fLoader(Me.EditRecord, rstData.Rows(0)) ' load up hidden div with data
    ' hide grid
    MyGrid.Style.Add("display", "none")
    EditRecord.Style.Add("display", "normal")
    ViewState("rstData") = rstData

End Sub

再一次,上面的代碼 - 非常簡單,非常簡單。

當我在給定的行上點擊編輯時,我們現在看到了這一點:

在此處輸入圖像描述

和保存按鈕代碼:

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

    Dim rstData As DataTable = ViewState("rstData")
    Call fWriterW(EditRecord, rstData.Rows(0))  ' div to table
    Call SaveTable(rstData, "tblHotelsA")  ' send table back to database

    LoadGrid()    ' refresh grid
    MyGrid.Style.Add("display", "normal")
    EditRecord.Style.Add("display", "none")


End Sub

再次注意代碼是多么簡單。 請注意,我可以將這兩個例程合並為一個(fwriterW 和 SaveTable)。 但是,通常在我們將數據從 Web 表單拉回表格后,我們可能希望在保存之前對數據執行一些附加過程或代碼。

所以,現在是循環代碼。 我們有兩個這樣的例程:

數據到網頁

網頁到數據表。

所以,這是循環控制部分:

首先是裝載機:

Public Sub fLoader(F As HtmlGenericControl, rst As DataRow)

    For Each c As System.Web.UI.Control In F.Controls
        Select Case c.GetType
            Case GetType(TextBox)
                Dim ctlC As TextBox = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
                    End If
                End If
            Case GetType(Label)
                Dim ctlC As Label = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
                    End If
                End If
            Case GetType(DropDownList)
                Dim ctlC As DropDownList = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        ctlC.Text = IIf(IsDBNull(rst(ctlC.Attributes("f"))), "", rst(ctlC.Attributes("f")))
                    End If
                End If
            Case GetType(CheckBox)
                Dim ctlC As CheckBox = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        ctlC.Checked = rst(ctlC.Attributes("f"))
                    End If
                End If
            Case GetType(RadioButtonList)
                Dim ctlC As RadioButtonList = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        ctlC.SelectedValue = rst(ctlC.Attributes("f"))
                    End If
                End If
        End Select
    Next

End Sub

如果您使用它們,您可以隨着時間的推移添加更多的控件類型。 因此,請注意上述如何循環控件,根據“f”屬性設置填充它們。

在我的全局套路中,我們也有

Public Sub fWriterW(f As HtmlGenericControl, rst As DataRow)

    For Each c As System.Web.UI.Control In f.Controls
        Select Case c.GetType
            Case GetType(TextBox)
                Dim ctlC As TextBox = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
                    End If
                End If
            Case GetType(Label)
                Dim ctlC As Label = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
                    End If
                End If
            Case GetType(DropDownList)
                Dim ctlC As DropDownList = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        rst(ctlC.Attributes("f")) = IIf(ctlC.Text = "", DBNull.Value, ctlC.Text)
                    End If
                End If
            Case GetType(CheckBox)
                Dim ctlC As CheckBox = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        rst(ctlC.Attributes("f")) = ctlC.Checked
                    End If
                End If

            Case GetType(RadioButtonList)
                Dim ctlC As RadioButtonList = c
                If Not ctlC.Attributes("f") Is Nothing Then
                    If rst.Table.Columns.Contains(ctlC.Attributes("f")) Then
                        rst(ctlC.Attributes("f")) = ctlC.SelectedValue
                    End If
                End If


        End Select
    Next

End Sub

這實際上只是第一個循環的逆過程。

因此,我們將這些例程傳遞給一個“div”(始終帶有 id 和 runat server)。

所以另外兩個輔助例程是:

Public Function MyrstP(sqlCmd As SqlCommand) As DataTable

    Dim rstData As New DataTable
    Using sqlCmd
        Using conn = New SqlConnection(My.Settings.TEST4)
            conn.Open()
            sqlCmd.Connection = conn
            rstData.Load(sqlCmd.ExecuteReader)
        End Using
    End Using
    Return rstData

End Function

同樣,我在我的所有代碼中都使用了上述所有人。 再次,超級容易。

然后是寫回表格的代碼:

Sub SaveTable(rstData As DataTable, strTable As String)

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand("select * FROM " & strTable, conn)
            Dim da As New SqlDataAdapter(cmdSQL)
            Dim daU As New SqlCommandBuilder(da)
            conn.Open()
            da.Update(rstData)
        End Using
    End Using

End Sub

所以,就是這樣。

以上實際上是一個完整的可重復使用的框架工作。 它現在允許您重新使用上面的代碼 - 允許輕松編輯任何數據。 而且您不會一遍又一遍地重寫相同的代碼。

采用上面的代碼給了你真正的 RAD 開發,並且非常容易在 web 表單中編輯記錄 - 事實上它變得像桌面軟件一樣簡單。

因此,在大多數情況下,循環頁面上的每個控件並不是那么有用。 但是,將控件放置在“div”中(帶有 id 和 runat=server)現在允許您傳遞該單個 div。 這也意味着您可以在一個頁面上包含多個部分——也許是一張賬單地址和客戶記錄表。

以上所有內容都只是簡單的工作 - 包括當您擁有母版頁時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM