将用户控件动态添加到 FlowLayoutPanel
Adding a User Control dynamically to a FlowLayoutPanel
我创建了一个 UserControl 并将其添加到 FlowLayoutPanel
。 UserControl 用于允许用户在表单中输入 material、成本和交付状态。当用户填写它时,我希望另一个 UserControl 出现在它下面的 FlowLayoutPanel
UserControl 只是根据输入到两个 TextBox
控件中的文本和两个 Checkbox
控件的状态生成一个字符串。它还有一个 属性 指示用户何时填写了足够的信息。我想用这个 属性 来表示生成一个新的 UserControl。
目前我在 FlowLayoutPanel
上有了我的第一个 UserControl,它成功地传递了字符串和 CreateNew
属性。
我遇到的问题是:
- 如何监控
CreateNew
是否已更改为 True?
- 如何向表单添加控件并为控件名称 +1 以供将来引用
- 一旦添加了新的控件,我需要监控新的
CreateNew
状态是否改变以重复循环
谁能给我指明正确的方向,这方面有很多信息,但我似乎无法从其他人那里找到任何有用的信息 problems/questions。
更新 1
感谢用户 Zaggler 的评论,我现在已经设法获得在 FlowLayoutPanel
上创建自己的新实例的控件。但是现在我遇到了一个新问题,它只创建了一个新的用户控件,然后就停止了。
这是我使用的代码:
用户控制代码
Public Class Alv_Product_Order_Control
Public OutString As String
Public Event CreateNew()
Dim CreateNewRaised As Boolean
Private Sub OutputString(sender As Object, e As EventArgs) Handles tbMaterial.TextChanged, tbCost.TextChanged,
cbDelivered.CheckedChanged, cbOrderPlaced.CheckedChanged
OutString = "¦¦" & tbMaterial.Text & "¦" & tbCost.Text & "¦"
If cbOrderPlaced.Checked = True Then
OutString = OutString & "Yes¦"
Else
OutString = OutString & "No¦"
End If
If cbDelivered.Checked = True Then
OutString = OutString & "Yes¦"
Else
OutString = OutString & "No¦"
End If
If tbCost.Text = "" Or tbMaterial.Text = "" Then
Else
If CreateNewRaised = False Then
RaiseEvent CreateNew() 'Raise the event that's used to signal adding a new control to the layout
CreateNewRaised = True 'Create A Latched Boolean that cannot change again in the future
End If
End If
End Sub
Public ReadOnly Property Alv_Product_Order_Control As String
Get
Return OutString 'Pass string back to main form
End Get
End Property
主窗体代码
Private Sub CreateSecondPOC() Handles POC1.CreateNew
FlowLayoutPanel1.Controls.Add(New Alveare_VB.Alv_Product_Order_Control)
End Sub
我猜这里的问题是 CreateSecondPOC
只处理第一个 POC1
的事件
如何创建一个新的 Alveare_VB.Alv_Product_Order_Control
,将其命名为 POC2 并添加一个处理程序来处理 POC2.CreateNew
并添加另一个控件?
编辑 2
我知道我已经找到了答案,但我想看看已经提到的这个内存泄漏。我已将以下答案中提供的代码更改为:
Private Sub CreateSecondPOC(ByVal sender As Object, ByVal e As System.EventArgs) Handles POC1.CreateNew
Try
Dim oldPoc = DirectCast(sender, Alveare_VB.Alv_Product_Order_Control)
RemoveHandler oldPoc.CreateNew, AddressOf CreateSecondPOC
Catch ex As Exception
Debug.Print(ex.Message)
End Try
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
我在 "RemoveHandler" 行收到以下错误:
Unable to cast object of type 'System.Windows.Forms.TextBox' to type 'Alveare_VB.Alv_Product_Order_Control'.
当写入文本框时会引发 CreateNew
事件,这是作为我假设的发件人传回的吗?现在不太确定该去哪里。
编辑 3
错误出在我的 UserControl
中,我发回了不正确的对象(在本例中为文本框)。我现在已经将 RaiseEvent
更改为 return 和 UserControl
作为对象。现在一切正常。
你可以把你的处理程序改成这样
Private Sub CreateSecondPOC() Handles POC1.CreateNew
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
我不确定您是否要继续处理该事件,即使它已被填充一次,即它是否可以被取消填充,然后重新填充,然后再次引发该事件?也许您想在填充后将其锁定,但这并不清楚。
您还可以将所有 POC
控件保存在一个容器中,只有在它们全部填充后才创建一个新控件。
编辑:
根据下面的评论,您应该在不再需要时删除事件处理程序以避免内存泄漏。这是一种方法
Private Sub CreateSecondPOC(sender As Object) Handles POC1.CreateNew
Dim oldPoc = DirectCast(sender, Alveare_VB.Alv_Product_Order_Control)
RemoveHandler oldPoc, AddressOf CreateSecondPOC
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
但是 last POC
控件的事件处理程序永远不会取消订阅。所以你也可以在关闭表单时做这样的事情
For Each poc In Me.FlowLayoutPanel1.Controls.OfType(Of Alveare_VB.Alv_Product_Order_Control)()
RemoveHandler poc.CreateNew, AddressOf CreateSecondPOC
Next poc
我在上面提到 您还可以将所有 POC
控件保存在一个容器中,这是跟踪控件的更好方法,而不是使用 FlowLayoutPanel 作为逻辑容器。只做对您有用的事情,并考虑删除处理程序。
我创建了一个 UserControl 并将其添加到 FlowLayoutPanel
。 UserControl 用于允许用户在表单中输入 material、成本和交付状态。当用户填写它时,我希望另一个 UserControl 出现在它下面的 FlowLayoutPanel
UserControl 只是根据输入到两个 TextBox
控件中的文本和两个 Checkbox
控件的状态生成一个字符串。它还有一个 属性 指示用户何时填写了足够的信息。我想用这个 属性 来表示生成一个新的 UserControl。
目前我在 FlowLayoutPanel
上有了我的第一个 UserControl,它成功地传递了字符串和 CreateNew
属性。
我遇到的问题是:
- 如何监控
CreateNew
是否已更改为 True? - 如何向表单添加控件并为控件名称 +1 以供将来引用
- 一旦添加了新的控件,我需要监控新的
CreateNew
状态是否改变以重复循环
谁能给我指明正确的方向,这方面有很多信息,但我似乎无法从其他人那里找到任何有用的信息 problems/questions。
更新 1
感谢用户 Zaggler 的评论,我现在已经设法获得在 FlowLayoutPanel
上创建自己的新实例的控件。但是现在我遇到了一个新问题,它只创建了一个新的用户控件,然后就停止了。
这是我使用的代码:
用户控制代码
Public Class Alv_Product_Order_Control
Public OutString As String
Public Event CreateNew()
Dim CreateNewRaised As Boolean
Private Sub OutputString(sender As Object, e As EventArgs) Handles tbMaterial.TextChanged, tbCost.TextChanged,
cbDelivered.CheckedChanged, cbOrderPlaced.CheckedChanged
OutString = "¦¦" & tbMaterial.Text & "¦" & tbCost.Text & "¦"
If cbOrderPlaced.Checked = True Then
OutString = OutString & "Yes¦"
Else
OutString = OutString & "No¦"
End If
If cbDelivered.Checked = True Then
OutString = OutString & "Yes¦"
Else
OutString = OutString & "No¦"
End If
If tbCost.Text = "" Or tbMaterial.Text = "" Then
Else
If CreateNewRaised = False Then
RaiseEvent CreateNew() 'Raise the event that's used to signal adding a new control to the layout
CreateNewRaised = True 'Create A Latched Boolean that cannot change again in the future
End If
End If
End Sub
Public ReadOnly Property Alv_Product_Order_Control As String
Get
Return OutString 'Pass string back to main form
End Get
End Property
主窗体代码
Private Sub CreateSecondPOC() Handles POC1.CreateNew
FlowLayoutPanel1.Controls.Add(New Alveare_VB.Alv_Product_Order_Control)
End Sub
我猜这里的问题是 CreateSecondPOC
只处理第一个 POC1
如何创建一个新的 Alveare_VB.Alv_Product_Order_Control
,将其命名为 POC2 并添加一个处理程序来处理 POC2.CreateNew
并添加另一个控件?
编辑 2
我知道我已经找到了答案,但我想看看已经提到的这个内存泄漏。我已将以下答案中提供的代码更改为:
Private Sub CreateSecondPOC(ByVal sender As Object, ByVal e As System.EventArgs) Handles POC1.CreateNew
Try
Dim oldPoc = DirectCast(sender, Alveare_VB.Alv_Product_Order_Control)
RemoveHandler oldPoc.CreateNew, AddressOf CreateSecondPOC
Catch ex As Exception
Debug.Print(ex.Message)
End Try
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
我在 "RemoveHandler" 行收到以下错误:
Unable to cast object of type 'System.Windows.Forms.TextBox' to type 'Alveare_VB.Alv_Product_Order_Control'.
当写入文本框时会引发 CreateNew
事件,这是作为我假设的发件人传回的吗?现在不太确定该去哪里。
编辑 3
错误出在我的 UserControl
中,我发回了不正确的对象(在本例中为文本框)。我现在已经将 RaiseEvent
更改为 return 和 UserControl
作为对象。现在一切正常。
你可以把你的处理程序改成这样
Private Sub CreateSecondPOC() Handles POC1.CreateNew
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
我不确定您是否要继续处理该事件,即使它已被填充一次,即它是否可以被取消填充,然后重新填充,然后再次引发该事件?也许您想在填充后将其锁定,但这并不清楚。
您还可以将所有 POC
控件保存在一个容器中,只有在它们全部填充后才创建一个新控件。
编辑:
根据下面的评论,您应该在不再需要时删除事件处理程序以避免内存泄漏。这是一种方法
Private Sub CreateSecondPOC(sender As Object) Handles POC1.CreateNew
Dim oldPoc = DirectCast(sender, Alveare_VB.Alv_Product_Order_Control)
RemoveHandler oldPoc, AddressOf CreateSecondPOC
Dim newPoc As New Alveare_VB.Alv_Product_Order_Control
AddHandler newPoc.CreateNew, AddressOf CreateSecondPOC
FlowLayoutPanel1.Controls.Add(newPoc)
End Sub
但是 last POC
控件的事件处理程序永远不会取消订阅。所以你也可以在关闭表单时做这样的事情
For Each poc In Me.FlowLayoutPanel1.Controls.OfType(Of Alveare_VB.Alv_Product_Order_Control)()
RemoveHandler poc.CreateNew, AddressOf CreateSecondPOC
Next poc
我在上面提到 您还可以将所有 POC
控件保存在一个容器中,这是跟踪控件的更好方法,而不是使用 FlowLayoutPanel 作为逻辑容器。只做对您有用的事情,并考虑删除处理程序。