[英]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.