我创建了一个UserControl并将其添加到FlowLayoutPanel
。 UserControl用于允许用户输入表单的材料,成本和交付状态。当用户填写完毕后,我希望在FlowLayoutPanel
UserControl只根据输入两个TextBox
控件的文本和两个Checkbox
控件的状态生成一个字符串。它还有一个属性,指示用户何时填写了足够的信息。我想使用此属性来指示生成新的UserControl。
目前我在FlowLayoutPanel
上有第一个UserControl,它成功传递了String和CreateNew
属性。
我遇到的问题是:
CreateNew
是否已更改为True?CreateNew
状态是否更改以重复循环任何人都可以指出我在这方面的正确方向,那里有很多关于此的信息,但我似乎无法从其他问题/问题中找到任何有用的东西。
更新1
感谢用户Zaggler的评论,我现在设法让控件在FlowLayoutPanel
上创建自己的新实例。但是现在我遇到了一个新问题,它只创建了一个新的用户控件,然后停止了。
以下是我使用的代码:
UserControl代码
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"上收到以下错误行:
无法转换类型为#System; Windows.Forms.TextBox'的对象。输入' Alveare_VB.Alv_Product_Order_Control'。
当写入文本框时会引发CreateNew
事件,这会像我假设的发件人那样被传回?现在还不确定该去哪里。
编辑3
错误发生在我的UserControl
中,我发送了错误的对象(在本例中是文本框)。我现在更改了RaiseEvent
以返回UserControl
作为对象。现在一切正常。
答案 0 :(得分:1)
您可以将处理程序更改为此类
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
但最后 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用作逻辑容器。只做适合自己的事情并考虑删除处理程序。