VB.NET: что случилось с управляющими массивами

Отсутствие управляющих массивов в VB.NET является проблемой для тех, кто учит массам.

  • Больше невозможно просто скопировать элемент управления, например текстовое поле, а затем вставить его (один или несколько раз) для создания массива элемента управления.
  • Код VB.NET для создания структуры, подобной массиву элементов управления, во всех книгах на VB.NET, которые я купил и онлайн, был намного длиннее и сложнее. Ему не хватает простоты кодирования массива управления, который можно найти в VB6.

Если вы ссылаетесь на библиотеку совместимости VB6, то там есть объекты, которые действуют почти как массивы управления. Чтобы понять, что я имею в виду, просто используйте мастер обновления VB.NET с программой, содержащей массив элементов управления. Код снова уродлив, но он работает. Плохая новость заключается в том, что Microsoft не гарантирует, что компоненты совместимости будут продолжать поддерживаться, и вы не должны их использовать.

Код VB.NET для создания и использования «массивов управления» намного длиннее и сложнее.

instagram viewer

По словам Microsoft, чтобы сделать что-то даже похожее на то, что вы можете сделать в VB 6, необходимо создать «простой компонент, который дублирует функциональность массива управления».

Вам нужен как новый класс, так и форма для хостинга, чтобы проиллюстрировать это. Класс фактически создает и уничтожает новые метки. Полный код класса выглядит следующим образом:

Открытый класс LabelArray
Наследует систему. Коллекции. CollectionBase
Частный ReadOnly HostForm As _
Система. Окна. Формы. форма
Открытая функция AddNewLabel () _
Как система. Окна. Формы. метка
'Создайте новый экземпляр класса Label.
Дим Алабел как новая система. Окна. Формы. метка
«Добавьте ярлык в коллекцию
внутренний список.
Мне. Список. Добавить (aLabel)
Добавьте ярлык в коллекцию элементов управления
формы, на которую ссылается поле HostForm.
HostForm. Органы управления. Добавить (aLabel)
'Установить начальные свойства для объекта Label.
этикетка. Top = Count * 25
этикетка. Ширина = 50
этикетка. Слева = 140
этикетка. Tag = Я. подсчитывать
этикетка. Текст = "Метка" & Я. Граф. Нанизывать
Возврат лейбла
Конечная функция
Public Sub New (_
ByVal хост как система. Окна. Формы. Форма)
HostForm = хост
Мне. AddNewLabel ()
End Sub
Публичное свойство ReadOnly по умолчанию _
Элемент (индекс ByVal как целое число) как _
Система. Окна. Формы. метка
Получить
Вернуть CType (Me. List. Элемент (индекс), _
Система. Окна. Формы. Метка)
Конец получить
Конечная недвижимость
Public Sub Remove ()
«Убедитесь, что есть ярлык для удаления.
Если я. Count> 0 Тогда
'Удалить последнюю метку, добавленную в массив
'из коллекции элементов управления формы хоста.
Обратите внимание на использование свойства по умолчанию в
доступ к массиву.
HostForm. Органы управления. Удалить (Я (Я. Количество - 1))
Мне. Список. RemoveAt (Me. Count - 1)
End If
End Sub
Конечный класс

Чтобы проиллюстрировать, как будет использоваться этот код класса, вы можете создать форму, которая вызывает его. Вы должны будете использовать код, показанный ниже в форме:

Открытый класс Form1. Наследует систему. Окна. Формы. Форма. #Region "Windows Form Designer сгенерированный код" Также необходимо добавить оператор: «MyControlArray = New LabelArray (Me) 'после вызова InitializeComponent () в. скрытый код региона. 'Объявить новый объект ButtonArray. Dim MyControlArray As LabelArray. Частный Sub btnLabelAdd_Click (_. ByVal отправитель как система. Объект, _. ByVal e As System. EventArgs) _. Обрабатывает btnLabelAdd. Нажмите. Вызовите метод AddNewLabel. 'MyControlArray. MyControlArray. AddNewLabel () 'Изменить свойство BackColor. кнопки 0. MyControlArray (0) .BackColor = _. Система. Рисунок. Цвет. Красный. End Sub. Частный Sub btnLabelRemove_Click (_. ByVal отправитель как система. Объект, _. ByVal e As System. EventArgs) _. Ручки btnLabelRemove. Нажмите. 'Вызовите метод удаления MyControlArray. MyControlArray. Удалять() End Sub. Конечный класс

Во-первых, это даже не делает работу во время разработки, как мы делали это в VB 6! И, во-вторых, они не находятся в массиве, они находятся в VB.NET Collection - вещь, которая отличается от массива.

Причина, по которой VB.NET не поддерживает VB 6 «управляющий массив», заключается в том, что не существует такого понятия, как «управляющий» «массив» (обратите внимание на изменение кавычек). VB 6 создает закулисную коллекцию и создает ее как массив для разработчика. Но это не массив, и у вас мало контроля над ним, кроме функций, предоставляемых через IDE.

VB.NET, с другой стороны, называет это тем, чем является: коллекцией объектов. И они передают ключи от королевства разработчику, создавая все это прямо под открытым небом.

В качестве примера такого рода преимуществ, которые это дает разработчику, в VB 6 элементы управления должны были быть одного типа, и они должны были иметь одинаковое имя. Так как это всего лишь объекты в VB.NET, вы можете делать их разными типами, давать им разные имена и при этом управлять ими в одной и той же коллекции объектов.

В этом примере одно и то же событие Click обрабатывает две кнопки и флажок и отображает, какая из них была нажата. Сделайте это в одной строке кода с VB 6!

Private Sub MixedControls_Click (_
ByVal отправитель как система. Объект, _
ByVal e As System. EventArgs) _
Обрабатывает Button1.Click, _
Button2.Click, _
CheckBox1.Click
«Заявление ниже должно быть одним длинным утверждением!
«Это на четырех линиях здесь, чтобы держать его узким
достаточно разместить на веб-странице
Label2.Text =
Microsoft. Visual Basic. Верно (отправитель. GetType. Нанизывать,
Лен (отправитель. GetType. Нанизывать) -
(InStr (отправитель. GetType. ToString, "Формы") + 5))
End Sub

Вычисление подстроки является довольно сложным, но это не совсем то, о чем мы здесь говорим. Вы можете сделать что-нибудь в событии Click. Например, вы можете использовать тип элемента управления в операторе If, чтобы делать разные вещи для разных элементов управления.

Отзывы группы по вычислительным исследованиям Фрэнка о массивах

Учебная группа Фрэнка предоставила пример с формой, которая имеет 4 метки и 2 кнопки. Кнопка 1 очищает метки, а кнопка 2 заполняет их. Хорошей идеей будет снова прочитать оригинальный вопрос Фрэнка и заметить, что в качестве примера он использовал цикл, который используется для очистки свойства Caption массива компонентов Label. Вот VB.NET-эквивалент этого кода VB 6. Этот код делает то, что изначально просил Фрэнк!

Открытый класс Form1. Наследует систему. Окна. Формы. Форма. #Region "Windows Form Designer сгенерированный код" Dim LabelArray (4) As Label. 'объявить массив меток. Частный Sub Form1_Load (_. ByVal отправитель как система. Объект, _. ByVal e As System. EventArgs) _. Ручки MyBase. Загрузка. SetControlArray () End Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. End Sub. Частный Sub Button1_Click (_. ByVal отправитель как система. Объект, _. ByVal e As System. EventArgs) _. Ручки Button1.Click. Кнопка 1 Очистить массив. Дим как целое. Для = 1 до 4. LabelArray (a) .Text = "" Следующий. End Sub. Частный Sub Button2_Click (_. ByVal отправитель как система. Объект, _. ByVal e As System. EventArgs) _. Ручки Button2.Click. Кнопка 2 Заполнить массив. Дим как целое. Для = 1 до 4. LabelArray (a) .Text = _. «Массив управления» и CStr (a) Следующий. End Sub. Конечный класс

Если вы поэкспериментируете с этим кодом, вы обнаружите, что в дополнение к настройке свойств меток вы также можете вызывать методы. Так почему же я (и Microsoft) приложили все усилия, чтобы создать «уродливый» код в первой части статьи?

Я должен не согласиться с тем, что это действительно «Control Array» в классическом смысле VB. Управляющий массив VB 6 - это поддерживаемая часть синтаксиса VB 6, а не просто методика. Фактически, возможно, способ описать этот пример состоит в том, что это массив элементов управления, а не массив элементов управления.

В первой части я жаловался, что пример Microsoft работает ТОЛЬКО во время выполнения, а не во время разработки. Вы можете добавлять и удалять элементы управления из формы динамически, но все это должно быть реализовано в коде. Вы не можете перетаскивать элементы управления, чтобы создать их, как вы можете в VB 6. Этот пример работает в основном во время разработки, а не во время выполнения. Вы не можете добавлять и удалять элементы управления динамически во время выполнения. В некотором смысле, это полная противоположность примера первой части.

Классический пример массива управления VB 6 - это тот же пример, который реализован в коде VB .NET. Здесь в коде VB 6 (это взято из Mezick & Hillier, Руководство по сертификационному экзамену Visual Basic 6, p 206 - слегка изменено, так как пример в книге приводит к элементам управления, которые не видны):

Dim MyTextBox как VB.TextBox. Статический intNumber как целое число. intNumber = intNumber + 1. Установите MyTextBox = _. Мне. Органы управления. Добавить ("VB.TextBox", _. "Текст" & intNumber) MyTextBox. Text = MyTextBox. Имя. MyTextBox. Visible = True. MyTextBox. Слева = _. (intNumber - 1) * 1200

Но, как согласны Microsoft (и я), управляющие массивы VB 6 невозможны в VB.NET. Таким образом, лучшее, что вы можете сделать, это дублировать функциональность. Моя статья дублировала функциональность, найденную в примере Mezick & Hillier. Код Исследовательской комиссии дублирует функциональность возможности устанавливать свойства и вызывать методы.

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

Джон Фаннон берет контрольные массивы

Джон написал: мне нужны управляющие массивы, потому что я хотел поместить простую таблицу чисел в форму во время выполнения. Я не хотел тошноты размещения их по отдельности, и я хотел использовать VB.NET. Microsoft предлагает очень подробное решение простой проблемы, но это очень большой кувалдой, чтобы сломать очень маленький орех. После некоторых экспериментов я в конце концов нашел решение. Вот как я это сделал.

Пример About Visual Basic выше показывает, как вы можете создать TextBox в форме, создав экземпляр объекта, установка свойств и добавление его в коллекцию Controls, которая является частью формы объект.

Dim txtDataShow As New TextBox
txtDataShow. Высота = 19
txtDataShow. Ширина = 80
txtDataShow. Местоположение = Новая точка (X, Y)
Мне. Органы управления. Добавить (txtDataShow)
Хотя решение Microsoft создает класс, я решил, что вместо этого можно было бы обернуть все это в подпрограмму. Каждый раз, когда вы вызываете эту подпрограмму, вы создаете новый экземпляр текстового поля в форме. Вот полный код:

Открытый класс Form1
Наследует систему. Окна. Формы. форма

#Region "Windows Form Designer сгенерированный код"

Частный Sub BtnStart_Click (_
ByVal отправитель как система. Объект, _
ByVal e As System. EventArgs) _
Ручки btnStart. щелчок

Дим я как целое
Dim sData As String
Для I = 1 до 5
sData = CStr (I)
Вызов AddDataShow (sData, I)
следующий
End Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal я как целое число)

Dim txtDataShow As New TextBox
Dim UserLft, UserTop As Integer
Dim X, Y As Integer
UserLft = 20
UserTop = 20
txtDataShow. Высота = 19
txtDataShow. Ширина = 25
txtDataShow. TextAlign = _
Горизонтальное выравнивание. Центр
txtDataShow. BorderStyle = _
BorderStyle. FixedSingle
txtDataShow. Text = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Высота
txtDataShow. Местоположение = Новая точка (X, Y)
Мне. Органы управления. Добавить (txtDataShow)
End Sub
Конечный класс
Очень хорошая мысль, Джон. Это, конечно, намного проще, чем код Microsoft... так что мне интересно, почему они так настаивали на этом?

Чтобы начать наше исследование, давайте попробуем изменить одно из назначений свойств в коде. Давай меняться

txtDataShow. Высота = 19
в

txtDataShow. Высота = 100
просто чтобы убедиться, что есть заметная разница.

Когда мы снова запустим код, мы получим... Whaaaat??? ... тоже самое. Без изменений вообще. Фактически, вы можете отобразить значение с помощью оператора вроде MsgBox (txtDataShow. Высота), и вы все равно получите 20 в качестве значения свойства независимо от того, что вы ему присваиваете. Почему это происходит?

Ответ в том, что мы не создаем свой собственный класс для создания объектов, мы просто добавляем вещи в другой класс, поэтому мы должны следовать правилам другого класса. И эти правила гласят, что вы не можете изменить свойство высоты. (Wellllll... вы можете. Если вы измените свойство Multiline на True, тогда вы можете изменить высоту.)

Почему VB.NET продвигается вперед и выполняет код, даже не задумываясь о том, что может быть что-то не так, когда, фактически, он полностью игнорирует ваше утверждение - это совершенно другая неприятность. Я мог бы предложить хотя бы предупреждение в компиляции, однако. (Подсказка! Подсказка! Подсказка! Microsoft слушает?)

Пример из части I наследуется от другого класса, и это делает свойства доступными для кода в наследующем классе. Изменение свойства высоты на 100 в этом примере дает нам ожидаемые результаты. (Опять таки... один отказ от ответственности: при создании нового экземпляра большого компонента Label он закрывает старый. Чтобы реально увидеть новые компоненты Label, вы должны добавить вызов метода aLabel. На передний план().)

Этот простой пример показывает, что, хотя мы МОЖЕМ просто добавить объекты в другой класс (и иногда это правильно), программируя контроль над объектами требует, чтобы мы получили их в классе, и наиболее организованным способом (смею сказать, «путь .NET» ??) является создание свойств и методов в новом производном классе для изменения вещи. Поначалу Джон оставался неубедительным. Он сказал, что его новый подход соответствует его цели, хотя существуют ограничения, связанные с тем, что он не является «COO» (правильно ориентированным на объект). Однако недавно Джон написал:

"... после написания набора из 5 текстовых полей во время выполнения я хотел обновить данные в последующей части программы - но ничего не изменилось - исходные данные все еще были там.

Я обнаружил, что могу обойти проблему, написав код для снятия старых ящиков и вернув их обратно с новыми данными. Лучший способ сделать это - использовать Меня. Обновить. Но эта проблема привлекла мое внимание к необходимости предоставить метод для вычитания текстовых полей, а также их добавления ».

Код Джона использовал глобальную переменную, чтобы отслеживать, сколько элементов управления было добавлено в форму, поэтому метод ...

Частный Sub Form1_Load (_
ByVal отправитель как система. Объект, _
ByVal e As System. EventArgs) _
Ручки MyBase. нагрузка
CntlCnt0 = Me. Органы управления. подсчитывать
End Sub

Тогда «последний» элемент управления может быть удален ...

N = я. Органы управления. Количество - 1
Мне. Органы управления. RemoveAt (N)
Джон отметил, что «возможно, это немного неуклюже».

Это способ, которым Microsoft отслеживает объекты в COM И в их «уродливом» примере кода выше.

Теперь я вернулся к проблеме динамического создания элементов управления в форме во время выполнения и снова посмотрел статьи «Что случилось с массивами элементов управления».

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

Джон продемонстрировал, как управлять размещением элементов управления в групповом окне, используя новые классы, которые он начал использовать. Может быть, Microsoft все-таки сделала это правильно в своем «уродливом» решении!

instagram story viewer