可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a form with a "Clear" button.
When the user clicks "Clear", I want to clear the value of all the visible elements on the form. In the case of date controls, I want to reset them to the current date.
All of my controls are contained on a Panel.
Right now, I'm doing this with the below code. Is there an easier way than manually checking for each control type? This method seems excessively unwieldy.
To make matters worse, in order to recursively clear controls inside sub-containers (i.e., a group box within the panel) I have to repeat the whole monster with an overloaded "GroupBox" version.
Edit: Thanks to your suggestions, the below code is greatly simplified.
Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click
'User clicks Clear, so clear all the controls within this panel
ClearAllControls(panMid, True) 'True indicates that yes, i want to recurse through sub-containers
End Sub
ClearAllControls(ByRef container As Panel, Optional Recurse As Boolean = True)
'Clear all of the controls within the container object
'If "Recurse" is true, then also clear controls within any sub-containers
Dim ctrl As Control
For Each ctrl In container.Controls
If (ctrl.GetType() Is GetType(TextBox)) Then
Dim txt As TextBox = CType(ctrl, TextBox)
txt.Text = ""
End If
If (ctrl.GetType() Is GetType(CheckBox)) Then
Dim chkbx As CheckBox = CType(ctrl, CheckBox)
chkbx.Checked = False
End If
If (ctrl.GetType() Is GetType(ComboBox)) Then
Dim cbobx As ComboBox = CType(ctrl, ComboBox)
cbobx.SelectedIndex = -1
End If
If (ctrl.GetType() Is GetType(DateTimePicker)) Then
Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
dtp.Value = Now()
End If
If Recurse Then
If (ctrl.GetType() Is GetType(Panel)) Then
Dim pnl As Panel = CType(ctrl, Panel)
ClearAllControls(pnl, Recurse)
End If
If ctrl.GetType() Is GetType(GroupBox) Then
Dim grbx As GroupBox = CType(ctrl, GroupBox)
ClearAllControls(grbx, Recurse)
End If
End If
Next
End Sub
@Theraccoonbear: I like your suggestion, but when I change the declaration to this:
Private Sub ClearAllControls(ByRef controls As ControlCollection, Optional ByVal Recurse As Boolean = True)
Then this line gives me "Unable to cast object of type 'ControlCollection' to type 'ControlCollection'.":
ClearAllControls(panMid.Controls)
回答1:
You can skip the GetType and CType dance with TryCast:
Dim dtp as DateTimePicker = TryCast(ctrl, DateTimePicker)
If dtp IsNot Nothing then dtp.Value = Now()
That'll save you about 10 lines.
An extension method off the Control class should keep it pretty tidy:
<Extension()> _
Public Shared Sub ClearValue(c as Control, recursive as Boolean)
Dim dtp as DateTimePicker = TryCast(c, DateTimePicker)
If dtp IsNot Nothing Then dtp.Value = Now()
' Blah, Blah, Blah
End Sub
Edit: If the thought of Evil extension methods that ignore NullReferenceExceptions don't make you cringe:
<Extension()> _
Public Shared Sub ClearValue(c as CheckBox)
If c IsNot Nothing Then c.Checked = False
End Sub
TryCast(ctrl, CheckBox).ClearValue()
回答2:
here is the code to get all control of a Form's All GroupControls
and you can do something in the GroupBox Control
Private Sub GetControls()
For Each GroupBoxCntrol As Control In Me.Controls
If TypeOf GroupBoxCntrol Is GroupBox Then
For Each cntrl As Control In GroupBoxCntrol.Controls
'do somethin here
Next
End If
Next
End Sub
回答3:
Why not just have one routine
ClearAllControls(ByRef container As Control, Optional ByVal Recurse As Boolean = True)
You can recurse into it regardless of what level in the hierarchy you begin the call, from the form level down to a single container.
Also, on the TextBox controls, I use Textbox.Text = String.Empty
回答4:
I've done something similar and this is basically how I went about doing it. The only change I might suggest would be instead of overloading the method, just make the passed in type a Control and you can use the same version for GroupBox, Panel, or any other container control that provides a .Controls property. Other than that, I think the definition of "clearing" a control can be somewhat ambiguous and thus there's no Clear() method belonging to the Control class so you need to implement what that means for your purposes for each control type.
回答5:
For Each c In CONTAINER.Controls
If TypeOf c Is TextBox Then
c.Text = ""
End If
Next
Replace the (CONTAINER) by the name of yours (it may be a FORM, a PANEL, a GROUPBOX)
Pay attention to which you had included your controls in.
回答6:
Here it works for all inner controls.
Add if any other controls do you need to clear.
Private Sub ClearAll()
Try
For Each ctrl As Control In Me.Controls
If ctrl.[GetType]().Name = "Panel" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "GroupBox" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "ComboBox" Then
Dim tb As ComboBox = TryCast(ctrl, ComboBox)
tb.SelectedText = ""
End If
If ctrl.[GetType]().Name = "TabControl" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "TextBox" Then
Dim tb As TextBox = TryCast(ctrl, TextBox)
tb.Clear()
End If
If ctrl.[GetType]().Name = "RadioButton" Then
Dim tb As RadioButton = TryCast(ctrl, RadioButton)
tb.Checked = False
End If
If ctrl.[GetType]().Name = "CheckBox" Then
Dim tb As CheckBox = TryCast(ctrl, CheckBox)
tb.Checked = False
End If
If ctrl.[GetType]().Name = "ComboBox" Then
Dim tb As ComboBox = TryCast(ctrl, ComboBox)
tb.SelectedIndex = 0
End If
If ctrl.[GetType]().Name = "RichTextBox" Then
Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
tb.Clear()
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub ClearControls(ByVal Type As Control)
Try
For Each ctrl As Control In Type.Controls
If ctrl.[GetType]().Name = "TextBox" Then
Dim tb As TextBox = TryCast(ctrl, TextBox)
tb.Clear()
End If
If ctrl.[GetType]().Name = "Panel" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "GroupBox" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "TabPage" Then
ClearControls(ctrl)
End If
If ctrl.[GetType]().Name = "ComboBox" Then
Dim tb As ComboBox = TryCast(ctrl, ComboBox)
tb.SelectedText = ""
End If
If ctrl.[GetType]().Name = "RadioButton" Then
Dim tb As RadioButton = TryCast(ctrl, RadioButton)
tb.Checked = False
End If
If ctrl.[GetType]().Name = "CheckBox" Then
Dim tb As CheckBox = TryCast(ctrl, CheckBox)
tb.Checked = False
End If
If ctrl.[GetType]().Name = "RichTextBox" Then
Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
tb.Clear()
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
回答7:
This comes straight from an article discussing techniques to use now that Control Arrays have been done away with going from VB6 to VB.NET.
Private Sub ClearForm(ByVal ctrlParent As Control)
Dim ctrl As Control
For Each ctrl In ctrlParent.Controls
If TypeOf ctrl Is TextBox Then
ctrl.Text = ""
End If
' If the control has children,
' recursively call this function
If ctrl.HasChildren Then
ClearForm(ctrl)
End If
Next
End Sub
回答8:
Public Sub raz(lst As Control.ControlCollection, Optional recursive As Boolean = True)
For Each ctrl As Control In lst
If TypeOf ctrl Is TextBox Then
CType(ctrl, TextBox).Clear()
End If
If TypeOf ctrl Is MaskedTextBox Then
CType(ctrl, MaskedTextBox).Clear()
End If
If TypeOf ctrl Is ComboBox Then
CType(ctrl, ComboBox).SelectedIndex = -1
End If
If TypeOf ctrl Is DateTimePicker Then
Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
dtp.CustomFormat = " "
End If
If TypeOf ctrl Is CheckedListBox Then
Dim clbox As CheckedListBox = CType(ctrl, CheckedListBox)
For i As Integer = 0 To clbox.Items.Count - 1
clbox.SetItemChecked(i, False)
Next
End If
If TypeOf ctrl Is RadioButton Then
CType(ctrl, RadioButton).Checked = False
End If
If recursive Then
If TypeOf ctrl Is GroupBox Then
raz(CType(ctrl, GroupBox).Controls)
End If
End If
Next
End Sub
回答9:
I present you my ControlIterator
Class
Source: http://pastebin.com/dubt4nPG
Some usage examples:
ControlIterator.Disable(CheckBox1)
ControlIterator.Enable({CheckBox1, CheckBox2})
ControlIterator.Check(Of CheckBox)(Me)
ControlIterator.Uncheck(Of CheckBox)(Me.GroupBox1)
ControlIterator.Hide(Of CheckBox)("1")
ControlIterator.PerformAction(Of CheckBox)(Sub(ctrl As CheckBox) ctrl.Visible = True)
ControlIterator.AsyncPerformAction(RichTextBox1,
Sub(rb As RichTextBox)
For n As Integer = 0 To 9
rb.AppendText(CStr(n))
Next
End Sub)
ControlIterator.PerformAction(Me.Controls, Sub(c As Control)
c.BackColor = Color.Green
End Sub)