Какой самый простой.NET-эквивалент массива управления VB6?

Возможно, я просто еще недостаточно хорошо знаю.NET, но мне еще предстоит найти удовлетворительный способ легко реализовать этот простой код VB6 в.NET (предположим, что этот код находится в форме с N CommandButtons в массиве Command1() и N Текстовые поля в массиве Text1()):

Private Sub Command1_Click(Index As Integer)

   Text1(Index).Text = Timer

End Sub

Я знаю, что это не очень полезный код, но он демонстрирует простоту использования массивов управления в VB6. Какой простейший эквивалент в C# или VB.NET?

8 ответов

Решение

Составьте общий список текстовых полей:

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 - это наличие одного обработчика событий, который обрабатывает несколько элементов управления:

Private Sub TextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _ 
        Handles TextBox1.TextChanged, _

        TextBox2.TextChanged, _

        TextBox3.TextChanged

End Sub

В.Net нет реального аналога 1 к 1. Конечно, вы можете создавать массивы или списки элементов управления определенного типа, но нет ничего, что сделает это автоматически.

Тем не менее, я никогда не видел массива элементов управления, который не может быть реорганизован в.Net для чего-то лучшего. В качестве примера можно привести ваш пример. В опубликованном вами сценарии вы используете управляющие массивы для сопряжения кнопки с текстовым полем. В.Net вы, вероятно, сделали бы это с помощью пользовательского элемента управления. Пользовательский элемент управления будет состоять из кнопки, текстового поля и, возможно, общего / статического таймера. Форма использует несколько экземпляров этого пользовательского элемента управления. Вы реализуете логику, необходимую для элемента управления, один раз, и она изолируется от собственного исходного файла, который можно отслеживать и редактировать в исходном элементе управления, не требуя слияния с большим классом форм, или его легко использовать повторно в нескольких формах или даже в нескольких проектах., Вам также не нужно беспокоиться о том, чтобы убедиться, что индекс командной кнопки совпадает с индексом текстового поля.

Использование настраиваемого элемента управления для этого вместо массива элементов управления аналогично использованию класса для группировки данных вместо массива, поскольку вместо индексов вы получаете имена.

Есть два аспекта.

.NET с готовностью поддерживает массивы элементов управления, VB6 просто пришлось использовать обходной путь, потому что в противном случае подключение событий было действительно трудным. В.NET динамическое связывание событий легко.

Однако конструктор форм.NET не поддерживает массивы элементов управления по простой причине: массивы элементов управления создаются / расширяются во время выполнения. Если вы знаете, сколько элементов управления вам нужно во время компиляции (рассуждения продолжаются), тогда вы даете им разные имена и не помещаете их в массив.

Я знаю, что это не очень полезный код

В том-то и дело. Зачем иметь функцию, если она бесполезна?

При необходимости вы также можете получить доступ к элементу управления по имени, что приведет к чему-то вроде этого:

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

Двумя основными преимуществами массивов элементов управления в VB6 были: (1) они давали вам возможность перебирать коллекцию элементов управления (2) позволяли вам делиться событиями между элементами управления

(1) может быть выполнено в.Net с использованием массива элементов управления (2) может быть достигнуто, если одно событие обрабатывает несколько элементов управления (синтаксис немного отличается, потому что вы используете sender аргумент вместо myArray(index)).

Одна приятная вещь в.Net заключается в том, что эти функции не связаны между собой. Так, например, у вас могут быть элементы управления, которые совместно используют события, даже если они не являются частью массива и имеют разные имена и даже другой тип. И вы можете перебирать коллекцию элементов управления, даже если они имеют совершенно разные события.

Библиотека совместимости VisualBasic .NET содержит массивы типизированных элементов управления. Это то, что мастер обновления использует для замены текущих массивов управления VB6.

Однако управляющий массив в VB6 - это просто набор объектов, в которых VB6 выполняет магию синтаксиса на поверхности. В мире.NET, удалив это, они навязывают лучшие практики.

В заключение, с появлением дженериков, ничто не мешает вам использовать

List<YourControl> MyControlArray.

Сделайте массив элементов управления.

TextBox[] textboxes = new TextBox[] {
    textBox1,
    textBox2,
    textBox3
};

Я знаю, что ответ пришел довольно поздно, но думаю, что нашел решение. Я не единственный бывший разработчик VB6, который боролся с этим ограничением VS. Давным-давно я пытался перенести разработанную мной CRM, но мне это не удалось, потому что у меня была жесткая зависимость массивов элементов управления (сотни в одной форме). Я прочитал много форумов и смог написать такой простой код:

VB.NET:

'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#:

//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 момента:

  1. А List поможет вам имитировать большую коллекцию элементов управления.
  2. typeof(Control) поможет вам определить тип элемента управления, который нужно добавить в список.
  3. Сохраняя "индекс" в качестве последнего символа (текстовое поле 1, текстовое поле 2,..., текстовое поле N), вы можете создать логический порядок.

Пример в режиме проектирования:

Бег:

Подобная логика может быть потенциально использованы в других технологий, таких как WPF, ASP.NET (Web Forms) или Xamarin (формы) -в моем формирующие общественное мнение. Я надеюсь, что этот фрагмент кода поможет большему количеству программистов в будущем.

Одно и то же событие нажатия может обрабатывать нажатия кнопок от нескольких кнопок в.Net. Затем вы можете добавить текстовое поле, чтобы найти в свойстве Tag?

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
Другие вопросы по тегам