Vb.net 每次调用ShowDialog时删除控件
我有一个表单,我只使用Vb.net 每次调用ShowDialog时删除控件,vb.net,showdialog,control-array,Vb.net,Showdialog,Control Array,我有一个表单,我只使用ShowDialog方法显示它。在显示的Form_事件中,我根据调用表单中设置的公共变量动态创建了一组标签和文本框 我知道表单没有关闭或销毁,只是隐藏在调用之间,因此我在我的form\u show事件顶部添加了代码,以清除以前调用中的任何控件,但这些控件没有被删除。我已经尝试了ctrl.Dispose(如下代码所示)和Me.Controls.Remove(ctrl)。两者都不会产生错误,但不会删除文本框,并在其上创建新的文本框。(由于某种原因 这是我第一次在.NET中动态创
ShowDialog
方法显示它。在显示的Form_
事件中,我根据调用表单中设置的公共变量动态创建了一组标签和文本框
我知道表单没有关闭或销毁,只是隐藏在调用之间,因此我在我的form\u show
事件顶部添加了代码,以清除以前调用中的任何控件,但这些控件没有被删除。我已经尝试了ctrl.Dispose
(如下代码所示)和Me.Controls.Remove(ctrl)
。两者都不会产生错误,但不会删除文本框,并在其上创建新的文本框。(由于某种原因
这是我第一次在.NET中动态创建/删除控件,因此我对VB6控件数组的渴望可能与错误有关
表单基于调用表单的公共ListView变量构建自身。调用表单确保此变量不是空变量,并且仅当用户正在编辑现有行时才选择项目
Public Class frmTableEdit
Private isNew As Boolean
Private inputText() As TextBox
Private Sub FormTableEdit_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
For Each ctrl As Control In Me.Controls
If TypeOf (ctrl) Is TextBox Or TypeOf (ctrl) Is Label Then
ctrl.Dispose()
End If
Next
With frmKioskData.TBLobj
Dim fieldCount As Integer = .Columns.Count - 1
isNew = .SelectedIndices.Count = 0
'(code setting size of form and location of OK/Cancel buttons is here)
ReDim inputText(fieldCount)
For i As Integer = 0 To fieldCount
Dim lbl As New Label, txt As New TextBox
inputText(i) = txt
Me.Controls.Add(lbl)
Me.Controls.Add(txt)
'(code setting size and and position of lbl & txt is here)
'lbl.Tag = i (I commented these lines out because I never used the
'txt.Tag = i Tag property, but can if a solution calls for it.)
lbl.Text = .Columns(i).Text
If isNew Then
txt.Text = ""
Else
txt.Text = .Items(.SelectedIndices(0)).SubItems(i).Text
End If
Next
End With
End Sub
End Class
如果@puropoix在上述评论中的建议对您不太合适,我认为在调用ShowDialog后处理表单是最简单和更有意义的,然后当您需要显示该表单时,您可以创建一个新实例,其中包含一个参数,告诉它要加载哪些动态控件 因此,在frmTableEdit中有一个新方法使用此参数:
Public Sub New(ByVal fieldCount As Integer)
InitializeComponent()
fieldCount = fieldCount 'Where fieldCount is a class variable
End Sub
当您从frmKioskData调用此表单时,您可以这样做:
Dim newTableEdit As New frmTableEdit(Me.TBLobj.Columns.Count - 1)
newTableEdit.ShowDialog()
newTableEdit.Dispose()
然后,frmEditTable的显示事件中的代码只需相应地添加控件,而无需删除旧控件:
ReDim inputText(fieldCount)
For i As Integer = 0 To fieldCount
Dim lbl As New Label, txt As New TextBox
inputText(i) = txt
Me.Controls.Add(lbl)
Me.Controls.Add(txt)
'(code setting size and and position of lbl & txt is here)
'lbl.Tag = i (I commented these lines out because I never used the
'txt.Tag = i Tag property, but can if a solution calls for it.)
lbl.Text = .Columns(i).Text
If isNew Then
txt.Text = ""
Else
txt.Text = .Items(.SelectedIndices(0)).SubItems(i).Text
End If
Next
如何获取isNew值取决于您-您可以将其作为第二个参数添加到表单的新参数中,或者以与现在相同的方式获取它…w/e。如果是我,我通常会将其作为另一个新参数添加。您可能会弄乱默认实例。为什么顶部循环使用
me
但稍后您会使用frmKioskData
ar它们是相同的东西吗?显示对话框的代码可能会有帮助。@puropoix,它们不一样;frmKioskData
是调用表单。我现在不在电脑前获取确切的代码,但我可以告诉你我使用的是frmTableEdit.ShowDialog()
而不是将变量声明为新表单。我通过调试知道,无论这是否为默认值,每次调用都会得到相同的实例(如预期的那样),并且每次都会触发显示的事件(也如预期的那样)。我怀疑问题出在Dispose
上,因为Me.Controls.Count
会随着每次连续调用而增加。inputText()的用途是什么
array?存储对文本框控件的附加引用将阻止它们被处理。如果使用显式表单引用并将处理循环放入Sub-Dispose(bool disposing)
中,它们应该很好地清理inputText()
的存在使我可以在单独的事件中按索引引用每个文本框。但是感谢您提供有关额外引用阻止处置@puropoix的提示;我不知道这一点(尽管现在看起来很明显)我强烈怀疑这就是我的问题的原因。我会在早上更新。你不需要一个控件引用数组,只需要列表(字符串)
中的控件名称给它们命名,比如“tbNumber”&I.ToString()
并在控件集合中使用名称引用它们。这种通用方法对我有效。在释放额外的引用(inputText
)后,我仍然存在同样的问题。在稍微调整后(主要是因为我的代码需要整个ListView
对象,而不仅仅是列。Count
),一切正常。