VB6控件数组最简单的.NET等效项是什么?

What's the simplest .NET equivalent of a VB6 control array?

也许我只是不太了解.NET,但是我还没有看到一种令人满意的方法来在.NET中轻松实现此简单的VB6代码(假设此代码位于数组Command1()和N中的N CommandButtons窗体上) 数组Text1()中的TextBoxes:

1
2
3
4
5
Private Sub Command1_Click(Index As Integer)

   Text1(Index).Text = Timer

End Sub

我知道这不是非常有用的代码,但是它演示了可以在VB6中轻松使用控件数组的代码。 C#或VB.NET中最简单的等效项是什么?


列出文本框的一般列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var textBoxes = new List<TextBox>();

// Create 10 textboxes in the collection
for (int i = 0; i < 10; i++)
{
    var textBox = new TextBox();
    textBox.Text ="Textbox" + i;
    textBoxes.Add(textBox);
}

// Loop through and set new values on textboxes in collection
for (int i = 0; i < textBoxes.Count; i++)
{
    textBoxes[i].Text ="New value" + i;
    // or like this
    var textBox = textBoxes[i];
    textBox.Text ="New val" + i;
}

VB .NET所做的另一件好事是拥有一个可以处理多个控件的事件处理程序:

1
2
3
4
5
6
7
8
Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles TextBox1.TextChanged, _

        TextBox2.TextChanged, _

        TextBox3.TextChanged

End Sub


.Net中没有真正的一对一模拟。当然,您可以创建特定类型的控件的数组或列表,但是没有什么可以自动为您完成此操作。

但是,我从未见过无法在.Net中重构为更好的控件数组。一个很好的例子就是你的例子。在您发布的方案中,您正在使用控件数组将按钮与文本框配对。在.Net中,您可能会使用自定义控件来执行此操作。自定义控件将包含一个按钮,一个文本框,以及一个共享/静态计时器。该窗体使用此自定义控件的多个实例。您只需实施一次控件所需的逻辑,然后将其隔离到自己的源文件中,即可在源代码控件中对其进行跟踪和编辑,而无需与较大的表单类合并,也可以轻松地在多个表单甚至多个项目中重复使用。您也不必担心确保命令按钮索引与文本框索引匹配。

为此,使用自定义控件而不是控件数组与使用类对数据而不是数组进行分组大致相似,因为您将获得名称而不是索引。


有两个方面。

.NET很容易支持控件数组,VB6只能使用一种解决方法,因为否则,连接事件真的很困难。在.NET中,动态连接事件很容易。

但是,.NET表单设计器不支持控件数组的原因很简单:控件数组是在运行时创建/扩展的。如果知道在编译时需要多少个控件(推理就行了),那么可以给它们指定不同的名称,而不必将它们放在数组中。

I know it's not very useful code

这就是重点。如果没有功能,为什么还要使用它?

如果需要,您还可以按名称访问控件,结果如下:

1
2
3
4
5
Private Sub Command_Click(sender As Object, e As EventArgs) Handles Command1.Click, Command2.Click …
    Dim name As String = DirectCast(sender, Control).Name
    Dim index As Integer = Integer.Parse(name.Substring("Command".Length))
    Controls(String.Format("Text {0}", index)).Text = Timer.Value.ToString()
End Sub

VisualBasic .NET的兼容性库包含强类型控制数组。这就是升级向导用来替换当前VB6控制阵列的内容。

但是,VB6中的控件数组只是对象的集合,而VB6在表面上做了一些语法魔术。在.NET世界中,通过删除此选项,他们正在强制采取更好的做法。

最后,随着泛型的出现,没有什么可以阻止您使用

1
List<YourControl> MyControlArray.

我知道我的回答还很晚,但是我想找到了解决方案。我不是唯一在VS的限制下苦苦挣扎的前VB6开发人员。很久以前,我试图迁移我设计的CRM,但是失败了,因为我对控制数组有很强的依赖性(一种形式有数百种)。我阅读了很多论坛,并且能够编写以下简单代码:

VB.NET:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'To declare the List of controls
Private textBoxes As List(Of TextBox) = New List(Of TextBox)()

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
    'To get all controls in the form
    For Each control In Controls

        'To search for the specific type that you want to create the array
        If control.[GetType]() = GetType(TextBox) Then
            textBoxes.Add(CType(control, TextBox))
        End If
    Next

    'To sort the labels by the ID
    textBoxes = textBoxes.OrderBy(Function(x) x.Name).ToList()
End Sub

C#:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//To declare the List of controls
private List<TextBox> textBoxes = new List<TextBox>();
private void Form1_Load(object sender, EventArgs e)
{
    //To get all controls in the form
    foreach (var control in Controls)
    {
        //To search for the specific type that you want to create the array
        if (control.GetType() == typeof(TextBox))
        {
            //To add the control to the List
            textBoxes.Add((TextBox)control);
        }
    }

    //To sort the labels by the ID
    textBoxes = textBoxes.OrderBy(x => x.Name).ToList();
}

有3点需要考虑:

  • List将帮助您模拟大量控件。
  • typeof(Control)将帮助您定义要添加到列表中的控件的类型。
  • 在将"索引"保留为最后一个字符(textBox1,textBox2,...,textBoxN)的同时,您可以创建逻辑顺序。
  • 设计模式下的示例:

    Many textboxes in one window

    正在运行:

    running example

    我认为,类似的逻辑可能会在WPF,ASP.NET(Web窗体)或Xamarin(窗体)等其他技术中使用。我希望这段代码将来可以帮助更多的程序员。


    VB6中控制阵列的两个主要优点是:
    (1)它们为您提供了一种遍历控件集合的方式
    (2)他们允许您在控件之间共享事件

    (1)可以使用一系列控件在.Net中完成
    (2)可以通过使一个事件处理多个控件来实现(语法有点不同,因为您使用了sender参数而不是myArray(index))。

    .Net的一件好事是这些功能是分离的。因此,例如,您可以具有共享事件的控件,即使它们不是数组的一部分,并且具有不同的名称,甚至具有不同的类型。即使控件具有完全不同的事件,也可以遍历控件的集合。


    相同的单击事件可以处理.Net中多个按钮的按下。然后可以添加文本框以在Tag属性中找到?

    1
    2
    3
    4
    5
    6
    7
    Private Sub AllButton_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click
      Dim c As Control = CType(sender, Control)
      Dim t As TextBox = FindControl(CType(c.Tag, String))
      If t Is Not Nothing Then
         t.Text ="Clicked"
      End If
    End Sub

    制作一系列控件。

    1
    2
    3
    4
    5
    TextBox[] textboxes = new TextBox[] {
        textBox1,
        textBox2,
        textBox3
    };

    推荐阅读