參考來源
動態生成子控制不是問題,重點是怎麼把對應的函式自動加進去。
範例一 - 動態生成 TextBox
Public Class Form
' 動態生成 TextBox
Private Sub Form_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
Dim myTextBox As TextBox
' const declare
Const x0 As Int32 = 20
Const y0 As Int32 = 20
Const w As Int32 = 100
Const h As Int32 = 30
Const hd As Int32 = 10
Const cnt As Int32 = 4
Dim i As Int32 = 0
' 動態生成 TextBox
For i = 0 To cnt - 1
myTextBox = New TextBox()
myTextBox.Text = "button" & i
myTextBox.Left = x0
myTextBox.Top = y0 + i * (h + hd)
myTextBox.Width = w
myTextBox.Height = h
Me.Controls.Add(myTextBox)
AddHandler myTextBox.Click, AddressOf myTextBoxClick ' 交附給函式
Next
End Sub
Private Sub myTextBoxClick(ByVal sender As Object, ByVal e As System.EventArgs)
System.Windows.Forms.MessageBox.Show(CType(sender, TextBox).Text)
End Sub
End Class
範例二 - 動態生成 Button (1)
初版的動態生成 Button 缺點不少,這裡是將 myButton 使用動態陣列,每個陣列名字都長得差不多,另外對應函式是用一個一個 map 起來的。原始碼如下
Public Class Form
' 動態生成按扭
Private myButton() As Button
Private Sub Form_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
' const declare
Const x0 As Int32 = 20
Const y0 As Int32 = 20
Const w As Int32 = 100
Const h As Int32 = 30
Const hd As Int32 = 10
Const cnt As Int32 = 4
Dim i As Int32 = 0
ReDim myButton(cnt)
' 動態生成 button
For i = 0 To cnt - 1
myButton(i) = New Button()
myButton(i).Text = "button" & i
myButton(i).Left = x0
myButton(i).Top = y0 + i * (h + hd)
myButton(i).Width = w
myButton(i).Height = h
Me.Controls.Add(myButton(i))
Next
' 進行函式對應
AddHandler myButton(0).Click, AddressOf Func0
AddHandler myButton(1).Click, AddressOf Func1
AddHandler myButton(2).Click, AddressOf Func2
AddHandler myButton(3).Click, AddressOf Func3
End Sub
Sub Func0()
MsgBox("func0")
End Sub
Sub Func1()
MsgBox("func1")
End Sub
Sub Func2()
MsgBox("func2")
End Sub
Sub Func3()
MsgBox("func3")
End Sub
End Class
範例三 - 動態生成 Button (2)
第二版動態生成按鈕改善了一點點,由於這幾顆按鈕做的事都一樣,所以便用委派方式給同一個函式執行,但實際上效果並不彰。
Public Class Form
' 動態生成按扭
Private myButton() As Button
Private Sub Form_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
' const declare
Const x0 As Int32 = 20
Const y0 As Int32 = 20
Const w As Int32 = 100
Const h As Int32 = 30
Const hd As Int32 = 10
Const cnt As Int32 = 4
Dim i As Int32 = 0
ReDim myButton(cnt)
' 動態生成 button
For i = 0 To cnt - 1
myButton(i) = New Button()
myButton(i).Text = "button" & i
myButton(i).Left = x0
myButton(i).Top = y0 + i * (h + hd)
myButton(i).Width = w
myButton(i).Height = h
Me.Controls.Add(myButton(i))
AddHandler myButton(i).Click, AddressOf myButtonClick
Next
End Sub
' 委派函式
Private Sub myButtonClick(ByVal sender As Object, ByVal e As System.EventArgs)
System.Windows.Forms.MessageBox.Show(CType(sender, Button).Text)
End Sub
End Class
範例四 - 動態生成 Button (3)
第三版動態生成按鈕改善了二個部份,我們可以借由自己寫的函式,把 Button Name 一次全換掉;除此之外,事實上 myButton 可以不用 array 方式建立,同時也可以不用宣告到全域。
注意的是那個 SetButtonName,它的引數記得是放 string,不要直接傳 Button 實體進去,傳 Button 實體進去的話,做法就要等 Button 全都建完之後才可以去呼叫 SetButtonName,效率不彰。
Public Class Form
' 動態生成按扭
' 設定按鈕名稱
Private Sub SetButtonName(ByRef btnName() as String, ByVal ParamArray Name() As String)
For i As Int32 = 0 To UBound(btnName) - 1
btnName(i) = Name(i)
Next i
End Sub
Private Sub Form_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
Dim btnName() As String
' const declare
Const x0 As Int32 = 20
Const y0 As Int32 = 20
Const w As Int32 = 100
Const h As Int32 = 30
Const hd As Int32 = 10
Const cnt As Int32 = 4
Dim i As Int32 = 0
Dim myButton As Button
ReDim btnName(cnt)
SetButtonName(btnName, "OK", "ERROR", "WARNNING", "RETRY")
' 動態生成 button
For i = 0 To cnt - 1
myButton = New Button()
myButton.Text = btnName(i)
myButton.Left = x0
myButton.Top = y0 + i * (h + hd)
myButton.Width = w
myButton.Height = h
Me.Controls.Add(myButton)
AddHandler myButton.click, AddressOf myButtonClick
Next
End Sub
Private Sub myButtonClick(ByVal sender As Object, ByVal e As System.EventArgs)
System.Windows.Forms.MessageBox.Show(CType(sender, Button).Text)
End Sub
End Class
總結
動態生成子控制大致上就像上述那樣,這裡提醒的是,如果每個 Button 實際上做的動態差很多,可以考慮把 myButton 宣告成陣列型態(這不是必然,不是用陣列去做時到時 mapping 會比較清楚、簡單),接著再手動去寫一份 map,至於 Rename 部份仍可以在建立實際 Button 時進行。最後結束前,再給最後一個範例,說明建立四個 button,名稱差很多,處理的東西也差很多,寫出來會是怎樣。
Public Class Form
' 動態生成按扭
Private Sub SetButtonName(ByRef btnName() As String, ByVal ParamArray Name() As String)
For i As Int32 = 0 To UBound(btnName) - 1
btnName(i) = Name(i)
Next i
End Sub
Private Sub Form_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
Dim BtnName() As String
' const declare
Const x0 As Int32 = 20
Const y0 As Int32 = 20
Const w As Int32 = 100
Const h As Int32 = 30
Const hd As Int32 = 10
Const cnt As Int32 = 4
Dim i As Int32 = 0
Dim myButton As Button
ReDim BtnName(cnt)
SetButtonName(BtnName, "OK", "ERROR", "WARNNING", "RETRY")
' 動態生成 button
For i = 0 To cnt - 1
myButton = New Button()
myButton.Text = BtnName(i)
myButton.Name = "btn_" & i ' 注意,這裡視為是 button ID, 不是 button text
myButton.Left = x0
myButton.Top = y0 + i * (h + hd)
myButton.Width = w
myButton.Height = h
Me.Controls.Add(myButton)
AddHandler myButton.Click, AddressOf myButtonClick
Next
End Sub
Dim btnIndex As Int32
Private Sub myButtonClick(ByVal sender As Object, ByVal e As System.EventArgs)
' 取得是由哪個 button ID 發出來的訊息
btnIndex = Val(CType(sender, Button).Name.Split("_")(1))
' 根據發出來的 button ID 做相對應的 function map,這部份比較麻煩
Select Case btnIndex
Case 0
Func0()
Case 1
Func1()
Case 2
Func2()
Case 3
Func3()
End Select
End Sub
Public Sub Func0()
MsgBox("func0")
End Sub
Public Sub Func1()
MsgBox("func1")
End Sub
Public Sub Func2()
MsgBox("func2")
End Sub
Public Sub Func3()
MsgBox("func3")
End Sub
Public Sub Func4()
MsgBox("func4")
End Sub
End Class
沒有留言:
張貼留言