【问题标题】:Is there any way to create a global function to clear TextBoxes?有没有办法创建一个全局函数来清除文本框?
【发布时间】:2019-12-13 14:23:33
【问题描述】:

我想知道是否有任何方法可以创建一个具有全局函数/方法/子的类 调用它会清除表单的一些文本框。我如何处理不同数量的文本框 每个表格都有?

当前代码仅清除预定义的 2 个框。谢谢。

Public Class ClearElements

    Public Sub CLEAR_TEXT(ByVal text1 As TextBox, ByVal text2 As TextBox)
        text1.Clear()
        text2.Clear()
    End Sub

End Class

【问题讨论】:

  • 您可以递归地遍历表单中的所有控件,如果 type = Textbox 则清除它。 stackoverflow.com/questions/4811229/…
  • 我以前做过。它清除了表单的所有框。我说的是一些盒子必须保持原状,一些盒子必须清除的情况。
  • 您需要测试每个文本框是否需要满足任何条件,然后确定是否要清除它。
  • 什么情况下有的通关有的没有?
  • 看看this post 然后:Me.DescendantControls().OfType(Of TextBox).ToList().ForEach(Sub(x) x.Clear())

标签: vb.net winforms


【解决方案1】:

有很多方法可以做到这一点。

您可以将文本框添加到列表中,并清除列表中的每个项目

Private ReadOnly someOfTheTextBoxes As New List(Of TextBox)

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    someOfTheTextBoxes.Add(TextBox1)
    someOfTheTextBoxes.Add(TextBox2)
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    For Each t In someOfTheTextBoxes
        t.Clear()
    Next
End Sub

或者做这个方法

Public Sub CLEAR_TEXT(textboxes As IEnumerable(Of TextBox))
    For Each t In textboxes
        t.Clear()
    Next
End Sub

并使用您的文本框列表调用它

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    CLEAR_TEXT(someOfTheTextBoxes)
End Sub

或者当场做一个数组传进去

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    CLEAR_TEXT({TextBox1, TextBox2})
End Sub

如果你对递归感兴趣,这里有一些我可以提供帮助的扩展

Module Extensions
    <Runtime.CompilerServices.Extension>
    Public Function ChildControls(parent As Control) As IEnumerable(Of Control)
        Return ChildControls(Of Control)(parent)
    End Function
    <Runtime.CompilerServices.Extension>
    Public Function ChildControls(Of TControl As Control)(parent As Control) As IEnumerable(Of TControl)
        Dim result As New List(Of TControl)
        For Each ctrl As Control In parent.Controls
            If TypeOf ctrl Is TControl Then result.Add(CType(ctrl, TControl))
            result.AddRange(ctrl.ChildControls(Of TControl)())
        Next
        Return result
    End Function
    <Runtime.CompilerServices.Extension>
    Public Function ForEach(Of TSource)(source As IEnumerable(Of TSource), action As Action(Of TSource)) As IEnumerable(Of TSource)
        For Each item As TSource In source
            action(item)
        Next item
        Return source
    End Function

    <Runtime.CompilerServices.Extension>
    Public Function ForEach(Of TSource)(source As IEnumerable(Of TSource), action As Action(Of TSource, Integer)) As IEnumerable(Of TSource)
        For i As Integer = 0 To source.Count() - 1
            action(source.ElementAt(i), i)
        Next
        Return source
    End Function
End Module

递归清除所有文本框

Me.ChildControls(Of TextBox).ForEach(Sub(t) t.Clear())

或 ForEach 在您的列表中

someOfTheTextBoxes.ForEach(Sub(t) t.Clear())

【讨论】:

  • 使用Yield 使代码更干净。例如,看看this post
  • @RezaAghaei Yield 也可以工作,但它不仅仅是更简洁的代码,代码的工作方式也会不同,即控件不会立即迭代,而是在随后的 LINQ 调用时迭代。我可以看到它如何更符合 IEnumerable 的精神。
【解决方案2】:

我们有这个:

您可以递归地遍历表单中的所有控件,如果 type = Textbox 则清除它。

但随后情节变厚了:

我以前做过。它清除了表单的所有框。我说的是有些盒子必须保持原状,有些盒子必须清除的情况。

这里的解决方案是两部分。首先,按照以下建议创建递归方法:

Public Sub ClearText(root As Control)
    For Each ctrl As Control In Root.Controls
        If TypeOf ctrl Is TextBox Then ctrl.Text = String.Empty
        ClearText(ctrl)
    Next ctrl
End Sub

或者这个:

Public Sub ClearText(root As IEnumerable(Of Control))
    For Each ctrl As Control In root
        If TypeOf ctrl Is TextBox Then ctrl.Text = String.Empty
        ClearText(ctrl.Controls)
    Next ctrl
End Sub

其次,在您的表单上,使用 PanelGroupBoxFlowLayoutPanel 等容器来清除您需要清除的 TextBox 控件。关键是您需要清除的所有 TextBox 控件(并且您要保留的任何一个)都不应位于同一个公共容器中。完成后,您可以将容器传递给上述方法之一。如果这与您的布局相混淆,您可以在表单的不同区域为控件集设置少量容器,然后只调用几次函数。

请记住,Panel 控件的样式可以设置为在父窗体上完全不留下可见的工件,并完全用于逻辑分组。上述方法的第二个版本还允许您创建您关心的控件(或控件容器)的数组或列表。

控制它的另一种方法是从 TextBox 继承自定义控件。你甚至不需要改变任何东西。重要的是控件现在是与常规文本框不同的类型,因此递归方法可以针对您的新控件类型而不是文本框。

【讨论】:

  • Option Strict On 禁止从“Control.ControlCollection”到“IEnumerable(Of Control)”的隐式转换。我不想关闭 Option Strict 来使用它。 ClearText(ctrl.Controls.Cast(Of Control)) 似乎可以修复它,但这是正确的吗?
  • 我忘记了ControlCollection 是脑死的并且没有实现IEnumerable(Of Control)。最好的解决方案可能是重载方法。
【解决方案3】:

在某些情况下我使用 For。

首先要知道你需要什么文本框或任何组件。 其次是要知道文本框(或任何其他组件)是在窗体(根)内还是在其他组件(如面板、组框、标签页)内……以及它们是否在其他组件内。

Example1: Form - GroupBox(x) - TabControl(y) - TabPage(z) - TextBox(n)

Example2: 表单---TextBox(x)

示例 3: 表单 - GroupBoox(x) - Panel(y) - TextBox(n)

等等。

您可以创建一些动画子/函数来完成更详细的事情。有两点很重要:

  1. 组件的路径(参见前面的示例)

  2. 组件的编号。如果您遵循示例 3,可能会是这样:

Form1 – GroupBox2 – Panel1 – TextBox3

重要提示:这些是组件的名称,您需要将它们全部枚举出来。

按照您的要求进行操作的简单方法是:

Public Sub CountTextBoxesAndClear(ByVal FormName As String, Optional ByVal myObject As Object = Nothing)
    Dim ArrayTextBoxName() As String
    Dim myTextBox As New TextBox
    Dim nTBOX As Integer

    'Path of component
    If myObject = Nothing Then myObject = My.Application.OpenForms.Item(FormName)
    'Bucle
    For i As Integer = 0 To myObject.Controls.Count - 1
        If myObject.Controls(i).GetType Is GetType(TextBox) Then
            'Counting
            nTBOX += 1
            'Redim array
            ReDim Preserve ArrayTextBoxName(nTBOX)
            'Get Component
            ArrayTextBoxName(nTBOX) = "TextBox" & nTBOX
            'Get Path
            myTextBox = myObject.Controls.Item(ArrayTextBoxName(nTBOX))
            'myTextBox = myObject.Controls.Item("TextBox" & nTBOX) '<< the same of above line
            Try
                'Clear TextBoxes
                myTextBox.Clear()
            Catch ex As NullReferenceException
                'A TextBox is Null, no error message
            End Try
        End If
    Next
End Sub

FormName 是表单的名称,带引号,例如“Form1”。

myObject 是包含文本框的对象,如果文本框位于名为 Panel1 的 Panel 内,则必须编写 Panel1(不带引号)。

Try/Catch:也许你需要Textbox1、TextBox2、Textbox4、Textbox5、AnotherTextBox1、AnotherTextBox2。

然后你打电话给你的潜艇:

CountTextBoxesAndClear("Form1")

如果文本框位于名为 Panel1 的面板中:

CountTextBoxesAndClear("Form1", Panel1)

您必须拥有文本框的总数,但仅对名为 TextBox[x] 的文本框清除(或执行任何操作)。

Try/Catch 管理错误,因为 TextBox3 不存在。但是,正确的方法是 Textbox1、TextBox2、Textbox3、Textbox4、AnotherTextBox1、AnotherTextBox2 并在您的子/函数中设置限制。

例如:

Public Sub CountTextBoxesAndClear(ByVal FormName As String, Optional ByVal myObject As Object = Nothing, Optional byval start as integer = 0, Optional byval finish as integer = 0)
    […tracatra…]
    For i As Integer = start To finish
        […tratra…]
    Next
End Sub

这是如何调用的:

CountTextBoxesAndClear("Form1", Nothing, 1, 4)

现在,您可以研究一下如何创建子函数/函数以了解组件的正确路径,并获取文本框、标签、组合框、复选框的内容和属性……

其他信息:

如果您在 VisualStudio 中工作,您就会知道,如果您更改组件的名称,所有代码都会自动更改。如果您使用 start/finish 变量作为数字,这是一个大问题,因为当您需要添加/删除或移动位置时,您必须手动更改函数中的所有开始/完成值,例如:

CountTextBoxesAndClear("Form1", Nothing, 8, 12)

现在您需要在八个位置添加一个新的 TextBox 并移动一个。你的潜艇看起来像这样:

CountTextBoxesAndClear("Form1", Nothing, 9, 13)

您可以创建一个将组件名称转换为整数的简单函数(此函数仅适用于两位数(0到99):

   Public Function ObjToInt(ByVal IntObject As Object) As Integer
        If IntObject IsNot Nothing Then
            Dim ref As Integer = Val(IntObject.Name.Substring(IntObject.Name.Length - 2))
            If ref = 0 Then
                ref = Val(IntObject.Name.Substring(IntObject.Name.Length - 1))
            End If
            Return ref
        Else
            Return 0
        End If
    End Function

你的子可能是这样写的:

CountTextBoxesAndClear("Form1", Nothing, ObjToInt(TextBox9), ObjToInt(TextBox13))

【讨论】:

  • 或者您可以在控件名称末尾使用单行获得数字:Return Integer.Parse(IntObject.Name.Reverse().TakeWhile(Function(c) Integer.TryParse(c)).Reverse()) 它将采用任意数量的数字......您不妨让它带一个 Control而不是 Object 用于一些强类型
  • 当你有 TextBox1 和 TextBox01 时这个方法会失败
  • 是的,它失败了,因为我们需要一个常量,在本例中是组件的名称:“TextBox”。这是一个字符串。如果我们使用“TextBox01”,则名称为“TextBox0”及其编号。所有名称必须相同,并且仅更改序列的编号。我假设枚举任何对象“01”不是一个数字,因为 01 对人来说是 1,但对计算机来说是另一回事。感谢您的评论,您的笔记和您的回答。我正在学习。
  • 如果我知道我可以拥有 10 多个控件,我会使用 TextBox01、02 等,因为它们会按名称排序最多 99 个。 TextBox2 > TextBox10 按字母顺序 TextBox02
【解决方案4】:

感谢您的出色解决方案。

我终于用 ParamArray 弄明白了

 Public Sub CLEAR_TEXTBOXES(ParamArray arr_textboxes() As TextBox)
    For Each textbox As TextBox In arr_textboxes
        textbox.Clear()
    Next
End Sub

然后我使用我想要的任何文本框调用类,

CLS_CLEAR_TEXTBOX.CLEAR_TEXTBOXES(TextBox1, TextBox2, Textbox7)

【讨论】:

    【解决方案5】:

    这是更短的方法。
    使用 ParamArray 和 Linq。

    Public Sub CLEAR_TEXT(ParamArray text As TextBox())
            text.ToList().ForEach(Sub(s) s.Clear())
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 2016-01-06
      • 2018-12-19
      相关资源
      最近更新 更多