Visual Basic .NET на уроках информатики

Использование массивов и коллекций для управления данными

Разбить на страницы
Показывать лекцию целиком

В этой лекции вы узнаете, как:

  • организовывать информацию в массивы фиксированной длины и динамические массивы;
  • сохранять данные массива при изменении его размера;
  • манипулировать коллекцией Controls формы;
  • использовать цикл For Each...Next для перебора объектов, входящих в коллекцию;
  • создавать собственные коллекции для работы со строковыми данными.
  • Управление информацией в приложении Microsoft Visual Basic .NET является очень важной задачей, и при возникновении более серьезных задач, для хранения и обработки данных вам потребуются дополнительные инструменты. В этой лекции вы узнаете, как организовать переменные и другую информацию в виде удобных контейнеров, называемых массивами. Массивы упрощают процесс управления данными, когда у вас несколько десятков или более элементов данных, и они дают прекрасное введение в методики работы с базами данных, о которых вы узнаете далее в этой книге. Вы также узнаете, как использовать для управления информацией в программе на Visual Basic группы объектов, называемые коллекциями, и как обрабатывать коллекции с помощью специального цикла For Each...Next. Рассмотренные массивы и коллекции вместе являются великолепными инструментами для управления большими объемами информации в программе.

    Что нового в Visual Basic .NET?

  • Массивы в Visual Basic .NET всегда отсчитываются с нуля, то есть младший элемент массива всегда имеет индекс 0. В Visual Basic 6 оператор Option Base позволял программистам устанавливать начало отсчета либо на 0, либо на 1. Option Base больше не поддерживается.
  • Так как массивы всегда отсчитываются с 0, их нельзя больше объявлять с помощью ключевого слова To с указанием нижней и верхней границ массива. Другой стороной такого положения дел является то, что оператор LBound всегда возвращает 0, так как нижняя граница массива всегда равна 0. (Однако оператор UBound продолжает возвращать старший индекс массива, который равен количеству элементов минус 1.)
  • Массивы могут теперь объявляться и им могут присваиваться данные с помощью одного и того же оператора программы. Например, синтаксис для объявления массива с именем myList() и добавления в него четырех элементов будет иметь вид

    Dim myList() as Integer = {5, 10, 15, 20}
  • Оператор ReDim в Visual Basic .NET по-прежнему доступен, хотя его и нельзя использовать для изменения количества размерностей в существующем массиве. Также нельзя использовать оператор ReDim при первоначальном объявлении.
  • В Visual Basic больше нет единого типа данных Collection. Вместо этого функциональность коллекций обеспечивается через пространство имен System.Collections библиотеки классов Microsoft .NET Framework. Используя System.Collections можно получить доступ к различным типам коллекций, таким, как Stack, Queue, Dictionary и Hashtable.
  • Visual Basic больше не поддерживает массивы элементов управления (коллекции элементов управления, которые используют одно и то же имя и обрабатываются как единая группа), и нельзя объединять элементы управления с помощью буфера обмена, как это делалось в Visual Basic 6. Однако по-прежнему можно сохранять элементы управления в массиве, если массив объявлен с типом объекта.
  • Работа с массивами переменных

    Массивы являются мощным и проверенным временем механизмом для хранения данных программы - разработчики BASIC, Pascal, C и других популярных языков программирования для ссылки на группы значений с помощью одного имени и обработки этих значений включали массивы в самые первые версии этих продуктов.

    Массивы полезны тем, что они помогают обрабатывать большие объемы данных такими способами, которые оказались бы нереализуемыми при использовании традиционных переменных. Например, представьте создание в программе бейсбольной доски счета девяти подач. Чтобы сохранить счет для каждой подачи, вы могли бы попытаться создать в программе две группы по 9 переменных (всего 18 переменных). Чтобы сделать их понятными, вы, вероятно, назвали бы их как-нибудь типа Inning1VisitingTeam, Inning1HomeTeam и т.д. Работа с этими переменными по отдельности потребовала бы значительного времени и места в программе. К счастью Visual Basic позволяет организовать группы похожих переменных в массив с одним общим именем и легким в использовании индексом. Например, чтобы хранить счет бейсбольной игры, можно создать двумерный (2 на 9) массив с именем Scoreboard. Как это сделать?

    Создание массива

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

    Информация в операторе объявления массива Описание
    Имя массива Имя, которое будет использовано для представления массива в программе. В основном, имена массивов подчиняются тем же правилам, что и имена переменных. (За дополнительной информацией о переменных обратитесь к лекции 5.)
    Тип данных Тип данных, хранимых в массиве. В большинстве случаев все переменные в массиве будут относиться к одному и тому же типу данных. Можно указать один из базовых типов данных, или, если вы не уверены в том, какой тип данных будет храниться в массиве. Если вы будете хранить данные разных типов, то можете указать тип Object.
    Число измерений Число измерений, содержащихся в массиве. Большинство массивов являются одномерными (список значений) или двумерными (таблица значений), но, если вы работаете со сложной математической моделью, такой, как трехмерная фигура, то можете указать дополнительные измерения.
    Число элементов Число элементов, содержащихся в массиве. Элементы в массиве непосредственно связаны с индексом массива. В Visual Basic .NET первый индекс массива всегда 0.
    Совет. Массивы, которые содержат заданное число элементов, называются массивами фиксированной длины или массивами с фиксированными границами. Массивы, которые содержат переменное число элементов (массивы, которые при работе программы могут расширяться), называются динамическими массивами.

    Объявление массива фиксированной длины

    Базовый синтаксис открытого массива фиксированной длины такой:

    Dim Имя_массива(объявление_индекса1, объявление_индекса 2, ...) As тип_данных

    Здесь важную роль играют следующие аргументы.

  • Dim - это ключевое слово, которое объявляет массив. Если вы помещаете массив в стандартный модуль, то используйте вместо него слово Public.
  • Имя_массива - это имя переменной массива.
  • объявление_индекса1 - это верхняя граница первого измерения массива, которая равняется количеству элементов минус 1.
  • объявление_индекса2 - это верхняя граница второго измерения массива, которая равняется количеству элементов минус 1. (Через запятую можно добавлять дополнительные измерения массива.)
  • тип_данных - это ключевое слово, соответствующее типу данных, которые будут содержаться в этом массиве.
  • Например, чтобы объявить одномерный строковый массив с именем Employees, которые может хранить 10 имен сотрудников (пронумерованных от 0 до 9), необходимо ввести в процедуре события следующую строку:

    Dim Employees(9) As String

    В стандартном модуле это же объявление массива будет выглядеть так:

    Public Employees(9) As String

    Когда вы создаете массив, Visual Basic выделяет для него место в памяти. На следующей иллюстрация показана концепция организации массива. 10 элементов массива пронумерованы от 0 до 9, а не от 1 до 10, так как индексы массива всегда начинаются с 0. (Оператор Option Base из Visual Basic 6, который позволял вам индексировать массивы, начиная с 1, больше не поддерживается.)

    Чтобы объявить открытый двумерный массив с именем Scoreboard, который может хранить две строки и девять столбцов данных типа короткого целого, нужно ввести в процедуре события или в верхней части формы такой оператор:

    Dim Scoreboard(1, 8) As Short

    Когда вы создаете двумерный массив, Visual Basic выделяет для него место в памяти. Затем вы можете использовать этот массив в вашей программе так, как будто это таблица значений, как показано на следующей иллюстрации. (В этом случае элементы массива пронумерованы от 0 до 1 и от 0 до 8.)

    Работа с элементами массива

    После того, как вы объявили массив с помощью ключевого слова Dim или Public, его можно использовать в вашей программе. Для ссылки на элемент массива используются имя массива и индекс массива, заключенный в круглые скобки. Индекс должен быть целым числом или выражением, которое при его вычислении дает в результате целое число. Например, индекс может быть числом 5, целочисленной переменной num или выражением типа "num - 1". (Часто используется переменная-счетчик цикла For $$\dots$$ Next.) Следующий оператор присваивает элементу с индексом 5 массива Employees, использовавшегося в предыдущем разделе, значение "Лесли":

    Employees(5) = "Лесли"

    В нашем массиве Employees это приведет к следующему результату.

    Аналогично следующий оператор присваивает элементу, расположенному в строке 0 и столбце 2 (начало третьей подачи) массива Scoreboard, приведенного в предыдущем разделе, значение 4:

    Scoreboard(0, 2) = 4

    В нашем массиве Scoreboard это приведет к следующему результату.

    Эту методику индексирования можно использовать для присвоения и получения значений элементов массива.

    Создание массива фиксированной длины для хранения температур

    В следующем упражнении одномерный массив с именем Temperatures используется для записи максимальных ежедневных температур в течение недели. Эта программа демонстрирует, как можно использовать массив для хранения и обработки группы связанных значений в форме. Переменная массива Temperatures объявляется в верхней части формы, а затем с помощью функции InputBox в цикле For $$\dots$$ Next (см. лекцию 7) этому массиву присваиваются температуры. Для указания каждого из элементов массива используется счетчик цикла. Затем с помощью цикла For $$\dots$$ Next и объекта текстового поля содержимое массива отображается в форме. Также вычисляется и отображается "средняя" максимальная температура.

    Функции LBound и UBound

    Для облегчения работы с массивом программа Fixed Array использует для проверки верхней границы (старшего индекса) массива функцию UBound. UBound - это старое ключевое слово BASIC и Visual Basic, которое используется до сих пор; оно позволяет обрабатывать массивы, не изучая операторов объявления, которые содержат точные указания на то, сколько элементов содержится в массиве. Тесно связанная с ней функция LBound, которая проверяет нижнюю границу массива, в Visual Basic .NET все еще присутствует, но так как все массивы Visual Basic .NET теперь имеют нижнюю границу, равную 0, эта функция просто возвращает нулевое значение. Функции UBound и LBound имеют следующий синтаксис

    LBound(Имя_массива)
    UBound(Имя_массива)

    где Имя_массива - это имя массива, которое было объявлено в проекте.

    Массив фиксированной длины

  • Запустите Microsoft Visual Studio и создайте в папке c:\vbnet03sbs\ Гл.11 новый проект с именем My Fixed Array.
  • Нарисуйте в форме текстовое поле.
  • Установите свойство Multiline объекта TextBox1 на значение True, чтобы можно было изменить размер этого объекта.
  • Измените размер объекта текстового поля так, чтобы он заполнял почти все пространство формы.
  • Нарисуйте в форме под этим объектом текстового поля два широких объекта кнопок, расположенных рядом друг с другом.
  • Установите для формы и ее объектов следующие свойства.

    Объект Свойство Установка
    TextBox1 ScrollBars Vertical
    Text пустой (empty)
    Button1 Text "Ввести температуры"
    Button2 Text "Отобразить температуры"
    Form1 Text "Фиксированный массив температур"

    Ваша форма должна выглядеть примерно так.

  • Чтобы просмотреть Редактор кода, щелкните в Обозревателе решений на кнопке View Code (Просмотреть код).
  • Прокрутите программный код формы в самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующее объявление массива:

    Dim Temperatures(6) As Single

    Этот оператор создает массив с именем Temperatures (имеющий тип Single ), который содержит семь элементов, пронумерованных от 0 до 6. Так как этот массив был объявлен в верхней части формы, он будет доступен во всех процедурах событий формы.

  • Снова отобразите форму, а затем щелкните дважды на кнопке Ввести температуры ( Button1 ). В Редакторе кода появится процедура события Button1_Click.
  • Чтобы запросить у пользователя температуры и загрузить ввод в массив, введите следующие операторы программы:

    Dim Prompt, Title As String
    Dim i As Short
    Prompt = "Введите максимальную температуру за день."
    For i = 0 To UBound(Temperatures)
      Title = "День "  (i + 1)
      Temperatures(i) = InputBox(Prompt, Title)
    Next

    При загрузке температур в элементы массива с 0 по 6 цикл For...Next использует в качестве индекса массива переменную-счетчик типа Short с именем i. Вместо того чтобы использовать простой синтаксис цикла For

    For i = 0 to 6

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

    For i = 0 To UBound(Temperatures)

    определяет верхнюю границу массива с помощью оператора UBound. Это методика достаточно гибкая; если в дальнейшем массив увеличится или уменьшится, цикл For автоматически подстроится под новый размер массива.

    Чтобы заполнить массив температурами, процедура события использует функцию InputBox, которая отображает текущую дату с помощью счетчика цикла For.

  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на кнопке Отобразить температуры ( Button2 ).
  • Введите в процедуре события Button2_Click операторы программы:

    Dim Result As String
    Dim i As Short
    Dim Total As Single = 0
    Result = "Максимальные температуры за неделю: "  vbCrLf  vbCrLf
    For i = 0 To UBound(Temperatures)
      Result = Result  "День "  (i + 1)  vbTab  _
      Temperatures(i)  vbCrLf
      Total = Total + Temperatures(i)
    Next
    Result = Result  vbCrLf  _
    "Средняя температура: "  Format(Total / 7, "0.0")
    TextBox1.Text = Result

    Эта процедура события использует цикл For $$\dots$$ Next для перебора элементов массива, и добавляет содержимое каждого из элементов в строковую переменную с именем Result, которая объявлена в верхней части процедуры события. Для того чтобы добавить в эту строковую переменную символ перевода строки ( vbCrLf ), символы табуляции ( vbTab ) и заголовки, я использовал несколько литеральных констант, специальных констант и оператор конкатенации строк (). Константа vbCrLf, использованная здесь впервые, содержит символ перевода строки и символ возврата каретки, и является эффективным способом создавать новые строки. Константа vbTab также используется здесь впервые и создает в строке Result между днем и значением температуры некоторое расстояние. В конце процедуры события определяется среднее значение для всех температур, и окончательная строка присваивается свойству Text объекта текстового поля:

    TextBox1.Text = Result
  • Чтобы сохранить проект, щелкните на кнопке Save All (Сохранить все) на стандартной панели инструментов.
  • Чтобы запустить программу, щелкните на кнопке Start (Начать).

    Примечание. Готовая программа Fixed Array лежит в папке c:\vbnet03sbs\Гл.11\fixed array.
  • Щелкните на кнопке Ввести температуры, а затем при появлении запросов от функции InputBox введите семь различных температур. Диалоговое окно функции InputBox выглядит так.

  • После того, как вы введете температуры, щелкните на кнопке Отобразить температуры. Visual Basic отобразит все температуры в текстовом поле и напечатает внизу их среднее значение. Ваш экран должен выглядеть примерно так.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Создание динамического массива

    Массивы удобны для работы со списками чисел, особенно если вы обрабатываете их с помощью циклов For $$\dots$$ Next. Но что, если при запуске программы вы не знаете, сколько места в массиве вам понадобится? Например, если нужно, чтобы пользователь выбирал, сколько температур вводить в программу Fixed Array?

    Visual Basic эффективно решает эту проблему с помощью специального "эластичного" контейнера, который называется динамическим массивом. Размерность динамических массивов определяется во время работы программы - либо тогда, когда пользователь указывает размер этого массива, либо когда логика программы определяет размер массива на основе некоторых условий. Выделение места под динамический массив требует нескольких действий. Хотя размер массива и не будет указан до тех пор, пока программа не будет запущена, при проектировании необходимо зарезервировать для него некоторые объем. Чтобы создать динамический массив, выполните такие базовые действия.

  • При разработке программы укажите имя и тип массива, не указывая при этом числа элементов этого массива. Например, чтобы создать динамический массив с именем Temperatures, введите

    Dim Temperatures() As Single
  • Добавьте код для определения числа элементов, которые должны быть в массиве во время выполнения программы. Вы можете запросить это число у пользователя с помощью функции InputBox, или вычислить необходимый объем с помощью свойств или другой логики. Например, следующие операторы получают размер массива от пользователя и присваивают его короткой целочисленной переменной Days:

    Dim Days As Short
    Days = InputBox("Сколько дней?", "Создание массива")
  • Чтобы задать размерность массива, используйте переменную в операторе ReDim (вычтите 1, так как массивы нумеруются с 0). Например, следующий оператор устанавливает размер массива Temperatures при выполнении программы с помощью переменной Days:

    ReDim Temperatures(Days - 1)
  • Единственным ограничением при использовании ReDim является то, что вы не должны пытаться изменить число измерений массива, который был объявлен ранее.
  • В цикле For $$\dots$$ Next для определения верхней границы массива используйте функцию UBound и произведите требуемую обработку массива, как показано здесь:

    For i = 0 to UBound(Temperatures)
      Temperatures(i) = InputBox(Prompt, Title)
    Next
  • В следующем упражнении вы будете использовать эти шаги для доработки программы Fixed Array так, что она с помощью динамического массива сможет обрабатывать любое количество температур.

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

  • Чтобы отобразить код программы проекта Fixed Array, откройте Редактор кода.
  • Прокрутите его вверх до начала кода формы, в которой вы первоначально объявили фиксированный массив Temperatures.
  • Удалите число 6 из объявления массива Temperatures, чтобы массив стал динамическим. Этот оператор должен выглядеть так:

    Dim Temperatures() As Single
  • Добавьте под объявлением массива Temperatures следующее объявление переменной:

    Dim Days As Integer

    Целочисленная переменная Days будет использована для получения ввода от пользователя и для задания размера динамического массива во время выполнения.

  • Прокрутите Редактор кода вниз, чтобы отобразить процедуру события Button1_Click, и измените ее код так, как показано ниже.

    Dim Prompt, Title As String
    Dim i As Short
    Prompt = "Введите максимальную температуру за день."
    Days = InputBox("Сколько дней?", "Создание массива")
    If Days > 0 Then ReDim Temperatures(Days - 1)
    For i = 0 To UBound (Temperatures)
      Title = "День "  (i + 1)
    Temperatures(i) = InputBox(Prompt, Title)
    Next

    Четвертая и пятая строки запрашивают у пользователя количество температур, которые надо сохранить, а затем этот ввод используется для задания размера динамического массива. Оператор If...Then используется для того, чтобы проверить, что число дней больше 0. (Задание размера массива с помощью числа, которое меньше 0, приведет к возникновению ошибки.) Так как для хранения температуры для первого дня используется индекс 0 массива, переменная Days при задании размера массива уменьшается на 1. Переменная Days не нужна для определения верхней границы в цикле For $$\dots$$ Next - как и в предыдущем примере, вместо этого используется функция UBound.

  • Прокрутите Редактор кода вниз, чтобы отобразить процедуру события Button2_Click. Измените ее код так, как показано в следующем фрагменте кода. (Измененные элементы выделены жирным.)

    Dim Result As String
    Dim i As Short
    Dim Total As Single = 0
    Result = "Максимальные температуры:"  vbCrLf  vbCrLf
    For i = 0 To UBound(Temperatures)
      Result = Result  "День "  (i + 1)  vbTab  _
      Temperatures(i)  vbCrLf
      Total = Total + Temperatures(i)
    Next
    Result = Result  vbCrLf  _
    "Средняя температура: "  Format(Total / Days, "0.0")
    TextBox1.Text = Result

    Переменная Days заменяет число 7 при вычислении средней температуры в нижней части этой процедуры события. Я также отредактировал заголовок "Максимальные температуры", который отображается в текстовом поле.

  • Сохраните изменения на диск.

    Примечание. На прилагаемом компакт-диске я дал этому проекту отдельное имя, чтобы отделить его от проекта Fixed Array. Готовая программа Dynamic Array лежит в папке c:\vbnet03sbs\ Гл.11\dynamic array.
  • Чтобы запустить программу, щелкните на кнопке Start (Начать).
  • Щелкните на кнопке Ввести температуры.
  • Когда увидите запрос на число дней, для которых вы хотите записать температуры, введите 5 и нажмите на OK.
  • Когда вас попросят ввести температуры, введите пять температур.
  • После того, как вы закончите вводить температуры, щелкните на кнопке Отобразить температуры. Программа отобразит в форме пять температур, а также их среднее значение. Ваш экран должен выглядеть примерно так.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Защита содержимого массива с помощью ReDim Preserve

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

    К счастью Visual Basic .NET предоставляет такую же полезную функцию для изменения размера массива, которую предоставлял и Visual Basic 6: ключевое слово Preserve, которое можно использовать для сохранения данных в массиве при изменении его размера. Синтаксис ключевого слова Preserve имеет следующий вид:

    ReDim Preserve Имя_массива(размер1, размер2, ...)

    В таком операторе изменения размера массив должен иметь такое же количество измерений и содержать тот же самый тип данных. В дополнение к этому существует дополнительное ограничение, состоящее в том, что вы можете изменить размер только последнего измерения массива. Например, если массив имеет два или более измерений, вы можете изменить размер только последнего измерения и сохранить при этом содержимое массива. (Одномерные массивы автоматически проходят этот тест, так что вы спокойно можете расширять размер таких динамических массивов с помощью ключевого слова Preserve.)

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

    Если вы с помощью следующей записи объявили динамический строковый массив с именем Philosophers:

    Dim Philosophers() As String

    измените его размер и добавьте в него данные с помощью кода, аналогичного следующему:

    ReDim Philosophers(200)
    Philosophers(200) = "Стив Гаррисон"

    Можно увеличить размер массива Philosophers до 301 элемента (0-300) и сохранить существующее содержимое с помощью следующей записи:

    ReDim Preserve Philosophers(300)

    Более сложный пример, включающий трехмерный массив, использует аналогичный синтаксис. Представьте, что вы используете в вашей программе трехмерный массив с именем myCube для хранения чисел с плавающей точкой одинарной точности. Массив myCube можно объявить с помощью следующей конструкции:

    Dim myCube(,,) As Single

    Затем можно изменить размер массива и добавить в него данные с помощью следующего кода:

    ReDim myCube(25, 25, 25)
    myCube(10, 1, 1) = 150.46

    после чего увеличить размер третьего измерения массива (сохранив при этом содержимое массива) с помощью следующей записи:

    ReDim Preserve myCube(25, 25, 50)

    Однако в этом примере может быть расширено только третье измерение - первое и второе измерения не могут быть изменены, если вы изменяете размер массива с помощью ключевого слова Preserve. Попытка изменить размер первого или второго измерений в этом примере приведет при выполнении оператора ReDim Preserve к ошибке времени исполнения.

    Немного поэкспериментируйте с ReDim Preserve и посмотрите, как вы можете его использовать, чтобы сделать ваши собственные массивы более гибкими и удобными.

    На этом работа с массивами пока закончена. В остальной части этой лекции речь пойдет о коллекциях.

    Работа с коллекциями объектов

    В предыдущем разделе вы узнали об использовании массивов для хранения информации при выполнении программы. В этом разделе вы изучите коллекции - еще один метод работы с объектами элементов управления и другими данными в программах на Visual Basic. Вы уже знаете, что объекты в форме хранятся вместе в одном и том же файле. Но знаете ли вы о том, что Visual Basic рассматривает эти объекты как члены одной и той же группы? В терминологии Visual Basic весь набор объектов формы называется коллекцией элементов управления ( Controls ). Коллекция Controls создается автоматически при создании новой формы, и когда вы добавляете в форму новые объекты, они автоматически становятся частью этой коллекции. На самом деле Visual Basic поддерживает несколько стандартных коллекций объектов, которые можно использовать в программах. Далее вы узнаете о базовых приемах работы с любыми попадающимися вам коллекциями.

    Каждая коллекция в программе имеет свое собственное имя, таким образом, вы можете ссылаться на нее как на отдельный элемент кода программы. Например, коллекция, содержащая все объекты формы, называется коллекцией Controls. Если в вашем проекте более одной формы, то чтобы различать коллекции Controls, относящиеся к этим формам, вы можете создать и использовать открытые переменные, ассоциированные с именами форм. (Об использовании открытых переменных для хранения данных форм вы узнаете в лекции 15) Вы можете добавлять элементы управления в коллекцию Controls формы даже программно.

    В дополнение к тому, что Visual Studio позволяет вам работать с объектами и коллекциями в ваших собственных программах, она еще позволяет просматривать вашу систему в поисках объектов других приложений и использовать их в ваших программах. Мы снова вернемся к этому вопросу в лекции 13 при изучении Visual Studio Object Browser (Обозревателя объектов).

    Ссылка на объекты в коллекции

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

    Controls(0).Text = "Бизнес"

    Этот оператор устанавливает свойство Text последнего объекта формы на значение "Бизнес". (Второй от конца созданный объект имеет индекс 1, третий от конца объект - индекс 2, и т.д.) Учитывая эту логику важно, чтобы вы никогда не связывали конкретный объект формы со значением индекса - если в коллекцию будет добавлен новый объект, этот новый объект получит индекс 0, а остальные индексы объектов увеличатся на 1.

    Следующий цикл For...Next отображает с помощью окна сообщения имена последних четырех добавленных в форму элементов управления:

    Dim i As Integer
    For i = 0 To 3
      MsgBox(Controls(i).Name)
    Next i

    Я указал этому циклу перебирать значения от 0 до 3, так как последний добавленный в форму элемент управления находится по индексу "0". В следующем разделе вы изучите более эффективный метод написания такого цикла.

    Написание циклов For Each ... Next

    Хотя на члены коллекции можно ссылаться индивидуально, наиболее эффективный способ работы с объектами в коллекциях - обрабатывать их как группы. На самом деле причиной существования коллекций является то, что вы, таким образом, можете более эффективно обрабатывать группы объектов: отобразить, переместить, отсортировать или изменить размер целой коллекции объектов одновременно.

    Чтобы выполнить эту задачу, вы можете использовать для последовательного перебора объектов в коллекции специальный цикл For Each...Next. Цикл For Each...Next аналогичен циклу For $$\dots$$ Next. Когда цикл For Each...Next используется вместе с коллекцией Controls, он выглядит так:

    Dim CtrlVar As Control
    ...
    For Each CtrlVar In Controls
      обработка объекта
    Next CtrlVar

    Переменная CtrlVar объявлена как переменная типа Control и представляет текущий объект коллекции. Controls (обратите внимание на конечную "s") - это класс коллекции, который представляет все объекты элементов управления текущей формы. Тело цикла используется для обработки отдельных объектов этой коллекции. Например, можно изменить свойства Enabled, Left, Top, Text или Visible объектов коллекции, или создать список имен всех объектов и поместить его в поле списка.

    Переменная CtrlVar представляет текущий объект цикла For Each...Next.

    Эксперименты с объектами из коллекции Controls

    В следующих упражнениях вы будете использовать код программы для манипуляций объектами на форме с помощью коллекции Controls. Ваш проект будет иметь три объекта кнопок, и вы создадите процедуры событий, которые будут изменять свойства Text каждого из этих объектов, перемещать объекты вправо и специальным образом обрабатывать один из объектов группы. Для манипуляций с объектами при щелчках пользователя на кнопках программа будет использовать три цикла For Each...Next.

    Использование цикла For Each ... Next для изменения свойств Text

  • Чтобы закрыть текущий проект, щелкните на команде Close Solution (Закрыть решение) в меню File (Файл).
  • В папке c:\vbnet03sbs\Гл.11 создайте новый проект Windows Application (Приложение Windows) на Visual Basic с именем My Controls Collection.
  • Используйте элемент управления Button и нарисуйте в левой части формы три объекта кнопок, как показано ниже.

  • С помощью окна Properties (Свойства) установите свойство Name третьего объекта кнопки ( Button3 ) на значение btnMoveObjects.
  • Сделайте на объекте первой кнопки ( Button1 ) формы двойной щелчок мышью. В Редакторе кода появится процедура события Button1_Click.
  • Введите следующие операторы программы:

    For Each ctrl In Controls
      ctrl.Text = "Нажми меня!"
    Next

    Это цикл For Each...Next перебирает коллекцию Controls формы по одному элементу управления и устанавливает свойство каждого из объектов на значение "Нажми меня!". В качестве переменной объекта цикл использует ctrl, которую вы объявите в следующем шаге.

  • Прокрутите программный код формы на самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующие комментарий и объявление переменной:

    ' Объявление переменной типа Control для представления элементов
    ' управления формы
    Dim ctrl As Control

    Это объявление глобальной переменной создает переменную типа Control, которая будет представлять в программе текущие элементы управления формы. Вы объявляете эту переменную в общей области объявлений формы, так что она будет доступна во всех процедурах событий этой формы. Теперь запустите программу и измените свойство Text для каждой кнопки формы.

  • Чтобы запустить программу, щелкните на кнопке Start (Начать), расположенной на стандартной панели инструментов.
  • Щелкните на первой кнопке ( Button1 ) формы. Процедура события Button1_Click изменяет свойство Text для каждого элемента управления из коллекции Controls. Ваша форма будет выглядеть примерно так.

  • Щелкните на кнопке Закрыть формы. Программа закроется. Теперь можно провести еще один эксперимент с коллекцией Controls. Используйте свойство Left для перемещения каждого элемента управления из коллекции Controls вправо.
  • Использование цикла For Each ... Next для перемещения элементов управления

  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на объекте второй кнопки ( Button2 ). Введите в процедуре события Button2_Click следующий код программы:

    For Each ctrl In Controls
      ctrl.Left = ctrl.Left + 25
    Next

    Каждый раз, когда пользователь будет щелкать на второй кнопке, этот цикл For Each...Next будет перебирать объекты в коллекции Controls и перемещать их на 25 пикселей вправо. (Чтобы переместить объекты на 25 пикселей влево, нужно вычитать 25.) Пиксель - это не зависящая от устройства единица измерения, которая позволяет точно расположить объекты в форме.

    Совет. В Visual Basic 6 для указания таких измерений вместо пикселей обычно использовались "твипы" (twips). За информацией о преобразовании существующего кода Visual Basic 6 с использованием измерения в твипах в код с использованием пикселей обратитесь к справочной системе Visual Studio и найдите в ней заголовок "ScaleMode Is Not Supported" ( ScaleMode не поддерживается).
  • Как видно из введенной выше процедуры события, переменная ctrl обозначает текущий объект в коллекции и содержит те же установки свойств, что и представляемый ею объект. В этом цикле вы изменяете свойство Left, которое определяет положение объекта относительно левой границы формы.
  • Щелкните на кнопке Start (Начать) стандартной панели инструментов. Программа запустится и в левой части формы появится три кнопки.
  • Щелкните несколько раз на второй кнопке. Каждый раз, когда вы щелкаете на этой кнопке, объекты перемещаются вправо. После пяти щелчков ваш экран будет выглядеть примерно так, как показано на рисунке вверху следующей страницы.
  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Перемещение всех объектов формы, конечно, необязательно. Visual Basic позволяет обрабатывать члены коллекции и по отдельности. В следующем упражнении вы узнаете о том, как при перемещении двух объектов кнопок вправо сохранить положение третьей кнопки неизменным.

    Использование свойства Name в цикле For Each ... Next

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

    Чтобы использовать свойство Name подобным образом, выделите объекты, которые вы хотите обработать, а затем отметьте их свойства Name. При переборе объектов формы в цикле For Each...Next используйте необходимое количество операторов If для проверки важного свойства Name, и обработайте эти объекты особым способом. Например, предположим, что вы хотите создать цикл For Each...Next, который перемещает объект по форме медленнее, чем все остальные объекты. Можно использовать оператор If...Then для нахождения свойства Name медленного объекта, а затем перемещать этот объект на более короткие дистанции, увеличивая его свойство Left не так сильно, как вы делаете это для других объектов.

    Совет. Если вы планируете использовать в цикле For Each...Next специальную обработку для нескольких объектов, то вместе с оператором If...Then вы можете использовать операторы ElseIf или структуру выбора Select Case.

    В следующем упражнении вы будете проверять свойство Name третьего объекта кнопки ( btnMoveObjects ) и обрабатывать ее в цикле For Each...Next особым образом. В конечном счете, вы получите процедуру события, которая перемещает вправо первые две кнопки, но оставляет на месте третью кнопку.

    Совет. В дополнение к свойству Name большинство объектов имеют свойство Tag. Аналогично свойству Name свойство Tag - это место, где можно сохранять строковые данные касающиеся объекта. Свойство Tag по умолчанию пусто, но вы можете присвоить ему некую информацию и проверять ее для однозначной идентификации объектов вашей программы, которые вы хотите обрабатывать особым образом.

    Использование свойства Name для специальной обработки элемента управления из коллекции Controls

  • Отобразите форму, а затем сделайте двойной щелчок мышью на объекте третьей кнопки. В Редакторе кода появится процедура события btnMoveObjects_Click. Помните, что в предыдущем примере вы изменили свойство Name этого объекта с Button3 на btnMoveObjects.
  • Введите в этой процедуре события следующий код программы:

    For Each ctrl In Controls
      If ctrl.Name <> "btnMoveObjects" Then
        ctrl.Left = ctrl.Left + 25
      End If
    Next

    Новой функцией этого цикла For Each...Next является оператор If...Then, который проверяет каждый член коллекции и смотрит, не равно ли его свойство Name значению btnMoveObjects. Если цикл находит этот маркер, он пропускает объект, не перемещая его. Заметьте, что, как и в предыдущем примере, переменная ctrl была объявлена в верхней части формы как переменная типа Control с областью видимости, распространяющейся на всю форму.

  • Щелкните на кнопке Save All (Сохранить все) стандартной панели инструментов.
  • Щелкните на кнопке Start (Начать). Программа запустится, и в форме появятся три объекта ее интерфейса.

    Примечание. Готовая программа Controls Collection расположена в папке c:\vbnet03sbs\Гл.11\controls collection.
  • Щелкните шесть или семь раз на третьем объекте кнопки. Каждый раз при щелчке на этой кнопке объекты формы перемещаются по экрану. Однако третья кнопка остается на своем месте, как показано на следующем рисунке.

    Специальная обработка одного объекта в коллекции может быть очень полезна. В этом случае использование свойства Name в цикле For Each...Next улучшает читаемость кода программы, предлагая многочисленные способы применения его для игр и графических программ. Когда вы будете использовать остальные типы коллекций Visual Basic, не забывайте о свойстве Name.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Создание собственных коллекций

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

    Новые коллекции объявляются в программе как переменные, и место, в котором вы их объявляете, определяет их область видимости, или область, в которой они сохраняют свои значения. Так как коллекции очень полезны, я обычно объявляю их в верхней части формы или в стандартном модуле. Новые объявления коллекций требуют записи

    Dim Имя_коллекции  As New Collection()

    где Имя_коллеции - это имя вашей коллекции. Если вы помещаете объявление коллекции в стандартном модуле, то вместо ключевого слова Dim следует использовать ключевое слово Public. После того, как вы создали коллекцию, с помощью метода Add в нее можно добавить ее члены, и узнать содержимое отдельных ее членов с помощью цикла For Each...Next.

    В следующем упражнении показано, как создать коллекцию для хранения строковых данных, представляющих интернет-адреса (URL), которые вы недавно использовали. Для соединения с сетью программа будет использовать метод Visual Basic с именем System.Diagnostics.Process.Start и ваш веб-браузер по умолчанию.

    Хранение интернет-адресов с помощью коллекции

  • Щелкните на команде Close Solution (Закрыть решение) в меню File (Файл). Текущий проект закроется.
  • В папке c:\vbnet03sbs\Гл.11 создайте новый проект на Visual Basic с именем My URL Collection.
  • В верхней части формы нарисуйте широкий объект текстового поля, отцентрированный по горизонтали.
  • В форме под этим объектом текстового поля нарисуйте два широких объекта кнопок, расположенных одна под другой.
  • Установите для формы и ее объектов следующие свойства:

    Объект Свойство Установка
    TextBox1 Text http://www.microsoft.com/mspress
    Button1 Text "Посетить сайт"
    Button2 Text "Создать список посещенных сайтов"
    Form1 Text "Коллекция URL"
  • Ваша форма должна выглядеть примерно так.

  • Чтобы отобразить Редактор кода, щелкните в Обозревателе решений на кнопке View Code (Просмотреть код).
  • Прокрутите программный код формы в самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующее объявление переменной:

    Dim URLsVisited As New Collection()

    Этот оператор создает новую коллекцию и присваивает ее переменной с именем URLsVisited. Так как вы расположили это объявление в верхней части формы, коллекция будет иметь область видимости, распространяющуюся на все процедуры событий формы.

  • Снова отобразите форму, сделайте двойной щелчок мышью на кнопке Посетить сайт, а затем введите в процедуре события Button1_Click следующий код:

    URLsVisited.Add(TextBox1.Text)
    System.Diagnostics.Process.Start(TextBox1.Text)

    Этот код программы использует метод Add для заполнения коллекции ее членами. Когда пользователь щелкает на объекте Button1, программа полагает, что в объект TextBox1 был введен правильный интернет-адрес. Каждый раз при щелчке на объекте Button1 текущий URL из TextBox1 копируется как строка в коллекцию URLsVisited. Далее вызывается метод System.Diagnostics.Process.Start с этим URL в качестве параметра. Так как параметр представляет собой URL, метод Start пытается открыть этот URL с помощью веб-браузера системы по умолчанию. (Если URL некорректен или соединение с интернетом не может быть установлено, то ошибку будет обрабатывать веб-браузер.)

    Примечание. Программа добавляет в коллекцию URLsVisited только те URL, которые вы указали в объекте TextBox1. Если вы переходите на дополнительные веб-сайты с помощью собственно браузера, эти сайты не будут добавлены в коллекцию. (О комплексном способе отслеживания веб-сайтов с помощью объектной модели Internet Explorer см. лекцию 21.)
  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на кнопке Создать список посещенных сайтов.
  • Введите в Редакторе кода следующий код программы:

    Dim URLName, AllURLs As String
    For Each URLName In URLsVisited
      AllURLs = AllURLs  URLName  vbCrLf
    Next URLName
    MsgBox(AllURLs, MsgBoxStyle.Information, "Посещенные сайты")

    Эта процедура события с помощью цикла For Each...Next и функции MsgBox печатает всю коллекцию. Этот код объявляет строковую переменную с именем URLName, которая хранит каждый из членов коллекции при его обработке, а его значение с помощью оператора конкатенации () и строковой константы vbCrLf добавляется в строку с именем AllURLs.

    Наконец, строка AllURLs, которая представляет всю коллекцию URLsVisited, отображается в окне сообщения. Я добавил к функции MsgBox аргумент MsgBoxStyle.Information, чтобы подчеркнуть, что отображаемый текст является общей информацией, а не предупреждением. ( MsgBoxStyle.Information также является встроенной константой Visual Basic.)

  • Чтобы сохранить изменения, щелкните на кнопке Save All (Сохранить все).
  • Примечание. Чтобы запустить программу URL Collection, ваш компьютер должен установить соединение с интернетом и иметь установленный веб-браузер, такой, как Microsoft Internet Explorer или Netscape Navigator.

    Запуск программы URL Collection

  • Чтобы запустить программу, щелкните на кнопке Start (Начать).

    Примечание. Готовая программа Collection лежит в папке c:\vbnet03sbs\Гл.11\url collection.

    Утилита содержит в текстовом поле URL адрес веб-сайта по умолчанию, так что при первом запуске вам не требуется вводить ваш собственный интернет-адрес.

  • Щелкните на кнопке Посетить сайт. Visual Basic добавит в коллекцию ), а затем откроет веб-браузер вашей системы по умолчанию и загрузит требуемую страницу, как показано на рисунке вверху следующей страницы. Если вам интересно, изучите содержимое этого веб-сайта.
  • Снова щелкните на форме. (Возможно, нужно будет щелкнуть на значке на панели задач Windows.)

  • Щелкните на кнопке Создать список посещенных сайтов. Visual Basic исполняет процедуру события для объекта Button2. Вы увидите такое окно сообщения.

  • Щелкните в окне сообщения на ).
  • Посетите еще несколько веб-сайтов с помощью формы Коллекция URL, а затем щелкните на кнопке Создать список посещенных сайтов. Каждый раз, когда вы щелкаете на кнопке Создать список посещенных сайтов, функция MsgBox расширяется для показа растущего списка URL, как показано ниже.

    Если вы посетили более десятка веб-сайтов, то вам понадобится заменить функцию MsgBox многострочным текстовым полем в форме.

  • Когда закончите, щелкните на кнопке Закрыть формы, а затем закройте веб-браузер.
  • Поздравляем! Вы узнали, как использовать коллекцию Controls и создавать новые коллекции и как обрабатывать их с помощью цикла For Each...Next. Эти навыки будут полезны всегда, когда вы будете работать с коллекциями.

    Следующий шаг: коллекции Visual Basic for Applications

    Если в будущем вы решите написать макросы Visual Basic для приложений Microsoft Office, то обнаружите, что в объектных моделях Microsoft Word, Microsoft Excel, Microsoft Access, Microsoft PowerPoint и некоторых других приложений, которые поддерживают язык программирования Visual Basic for Applications, коллекции играют очень важную роль. Например, в Word все открытые документы текстового процессора хранятся в коллекции Documents, а каждый параграф текущего документа - в коллекции Paragraphs. Вы можете манипулировать этими коллекциями с помощью цикла For Each...Next точно так же, как вы делали это с другими коллекциями из предыдущих примеров.

    Например, следующий пример кода является частью макроса Word 2002, который использует цикл For Each...Next для проверки каждого открытого документа из коллекции Documents на предмет имени файла MyLetter.doc. Если этот файл в коллекции найден, макрос сохраняет его с помощью метода Save. Если файл в коллекции не найден, макрос пытается открыть этот файл из папки My Documents, расположенной на диске C.

    Dim aDoc As Object
    Dim docFound As Boolean
    Dim docLocation As String
    docFound = False
    docLocation = "c:\my documents\myletter.doc"
    For Each aDoc In Documents
      If InStr(1, aDoc.Name, "myletter.doc", 1) Then
        docFound = True
        aDoc.Save
        Exit For
      End If
    Next aDoc
    If docFound = False Then
      Documents.Open FileName:=docLocation
    End If
    Совет. Этот пример макроса для Word 2002 демонстрирует, как можно использовать коллекции в Visual Basic for Applications, но этот исходный код разработан для Word, а не для компилятора Visual Basic. Чтобы его проверить, необходимо запустить Word, щелкнуть на команде Macros (Макросы:) из подменю Macro (Макрос) меню Tools (Сервис), создать новое имя для макроса, а затем ввести этот код с помощью специального редактора макросов Word. (Если вы не находитесь в Word, то коллекция Documents не будет иметь для компилятора никакого смысла.)

    Макрос начинается с объявления трех переменных. Объектная переменная aDoc представляет текущий элемент коллекции в цикле For Each...Next. Переменной Boolean с именем docFound будет присвоено логическое значение True, если документ в коллекции Documents найден. Строковая переменная docLocation будет содержать путь файла MyLetter.doc на диске. (Эта процедура предполагает, что файл MyLetter.doc находится в папке My Documents на диске C.)

    Цикл For Each...Next перебирает все документы в коллекции Documents и ищет файл MyLetter. Если файл с помощью функции InStr (которая ищет одну строку в другой) обнаружен, то файл сохраняется. Если файл не найден, макрос пытается открыть его с помощью метода Open объекта Documents. Также обратите внимание на оператор Exit For, который используется для выхода из цикла For Each...Next, когда файл MyLetter найден и сохранен на диск. Exit For - это специальный оператор программы, который можно использовать для выхода из циклов For...Next или For Each...Next, когда продолжение их работы становится нежелательным. В нашем примере, если файл MyLetter.doc в коллекции уже найден, продолжение поиска будет безрезультатно. Здесь оператор Exit For предоставляет удобный способ остановить цикл сразу, как только его задача выполнена.

    Краткая справка по лекции 11

    Чтобы Сделайте следующее
    Создать массив Задайте размерность массива с помощью ключевого слова Dim. Например: Dim Employees(9) As String
    Создать открытый массив Задайте размерность массива с помощью ключевого слова Public и разместите его объявление в стандартном модуле. Например: Public Employees(9) As String
    Поместить значение в массив Укажите имя массива, индекс элемента массива и значение. Например: Employees(5) = "Leslie"
    Отформатировать текстовую строку с использованием символов возврата каретки и табуляции Используйте в коде программы константы vbCrLf и vbTab. (Чтобы добавить эти значения, используйте оператор .)
    Создать динамический массив При объявлении укажите имя и тип массива, но не указывайте количество его элементов. (Если массив имеет несколько измерений, вставьте запятые между измерениями, но не вводите числа.) При выполнении программы укажите размер массива с помощью оператора ReDim. Например: ReDim Temperatures(10)
    Обработать элементы массива

    Напишите цикл For $$\dots$$ Next, который использует переменную-счетчик цикла для адресации каждого из элементов этого массива. Например:

    Dim i As Short
    Dim Total As Single
    For i = 0 To UBound(Temperatures)
      Total = Total + Temperatures(i)
    Next
    Изменить размер массива и сохранить в нем предыдущие данные Используйте в операторе ReDim ключевое слово Preserve. Например: ReDim Preserve myCube(25, 25, 50)
    Обработать объекты в коллекции

    Напишите цикл For Each $$\dots$$ Next, который адресует каждый член коллекции по отдельности. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      ctrl.Text = "Нажми меня!"
    Next
    Переместить объекты из коллекции Controls по экрану слева направо

    Измените в цикле For Each $$\dots$$ Next свойство Control.Left каждого из объектов коллекции. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      Ctrl.Left = Ctrl.Left + 25
    Next Ctrl
    Использовать для объекта в коллекции специальную обработку

    Проверьте с помощью цикла For Each $$\dots$$ Next свойство Name объекта из коллекции. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      If ctrl.Name <> "btnMoveObjects" Then
      ctrl.Left = ctrl.Left + 25
      End If
    Next
    Создать новую коллекцию и добавить в нее члены

    Объявите переменную с помощью записи New Collection. Для добавления членов используйте метод Add. Например:

    Dim URLsVisited As New Collection()
    URLsVisited.Add(TextBox1.Text)
    Страницы:

    В этой лекции вы узнаете, как:

  • организовывать информацию в массивы фиксированной длины и динамические массивы;
  • сохранять данные массива при изменении его размера;
  • манипулировать коллекцией Controls формы;
  • использовать цикл For Each...Next для перебора объектов, входящих в коллекцию;
  • создавать собственные коллекции для работы со строковыми данными.
  • Управление информацией в приложении Microsoft Visual Basic .NET является очень важной задачей, и при возникновении более серьезных задач, для хранения и обработки данных вам потребуются дополнительные инструменты. В этой лекции вы узнаете, как организовать переменные и другую информацию в виде удобных контейнеров, называемых массивами. Массивы упрощают процесс управления данными, когда у вас несколько десятков или более элементов данных, и они дают прекрасное введение в методики работы с базами данных, о которых вы узнаете далее в этой книге. Вы также узнаете, как использовать для управления информацией в программе на Visual Basic группы объектов, называемые коллекциями, и как обрабатывать коллекции с помощью специального цикла For Each...Next. Рассмотренные массивы и коллекции вместе являются великолепными инструментами для управления большими объемами информации в программе.

    Что нового в Visual Basic .NET?

  • Массивы в Visual Basic .NET всегда отсчитываются с нуля, то есть младший элемент массива всегда имеет индекс 0. В Visual Basic 6 оператор Option Base позволял программистам устанавливать начало отсчета либо на 0, либо на 1. Option Base больше не поддерживается.
  • Так как массивы всегда отсчитываются с 0, их нельзя больше объявлять с помощью ключевого слова To с указанием нижней и верхней границ массива. Другой стороной такого положения дел является то, что оператор LBound всегда возвращает 0, так как нижняя граница массива всегда равна 0. (Однако оператор UBound продолжает возвращать старший индекс массива, который равен количеству элементов минус 1.)
  • Массивы могут теперь объявляться и им могут присваиваться данные с помощью одного и того же оператора программы. Например, синтаксис для объявления массива с именем myList() и добавления в него четырех элементов будет иметь вид

    Dim myList() as Integer = {5, 10, 15, 20}
  • Оператор ReDim в Visual Basic .NET по-прежнему доступен, хотя его и нельзя использовать для изменения количества размерностей в существующем массиве. Также нельзя использовать оператор ReDim при первоначальном объявлении.
  • В Visual Basic больше нет единого типа данных Collection. Вместо этого функциональность коллекций обеспечивается через пространство имен System.Collections библиотеки классов Microsoft .NET Framework. Используя System.Collections можно получить доступ к различным типам коллекций, таким, как Stack, Queue, Dictionary и Hashtable.
  • Visual Basic больше не поддерживает массивы элементов управления (коллекции элементов управления, которые используют одно и то же имя и обрабатываются как единая группа), и нельзя объединять элементы управления с помощью буфера обмена, как это делалось в Visual Basic 6. Однако по-прежнему можно сохранять элементы управления в массиве, если массив объявлен с типом объекта.
  • Работа с массивами переменных

    Массивы являются мощным и проверенным временем механизмом для хранения данных программы - разработчики BASIC, Pascal, C и других популярных языков программирования для ссылки на группы значений с помощью одного имени и обработки этих значений включали массивы в самые первые версии этих продуктов.

    Массивы полезны тем, что они помогают обрабатывать большие объемы данных такими способами, которые оказались бы нереализуемыми при использовании традиционных переменных. Например, представьте создание в программе бейсбольной доски счета девяти подач. Чтобы сохранить счет для каждой подачи, вы могли бы попытаться создать в программе две группы по 9 переменных (всего 18 переменных). Чтобы сделать их понятными, вы, вероятно, назвали бы их как-нибудь типа Inning1VisitingTeam, Inning1HomeTeam и т.д. Работа с этими переменными по отдельности потребовала бы значительного времени и места в программе. К счастью Visual Basic позволяет организовать группы похожих переменных в массив с одним общим именем и легким в использовании индексом. Например, чтобы хранить счет бейсбольной игры, можно создать двумерный (2 на 9) массив с именем Scoreboard. Как это сделать?

    Создание массива

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

    Информация в операторе объявления массива Описание
    Имя массива Имя, которое будет использовано для представления массива в программе. В основном, имена массивов подчиняются тем же правилам, что и имена переменных. (За дополнительной информацией о переменных обратитесь к лекции 5.)
    Тип данных Тип данных, хранимых в массиве. В большинстве случаев все переменные в массиве будут относиться к одному и тому же типу данных. Можно указать один из базовых типов данных, или, если вы не уверены в том, какой тип данных будет храниться в массиве. Если вы будете хранить данные разных типов, то можете указать тип Object.
    Число измерений Число измерений, содержащихся в массиве. Большинство массивов являются одномерными (список значений) или двумерными (таблица значений), но, если вы работаете со сложной математической моделью, такой, как трехмерная фигура, то можете указать дополнительные измерения.
    Число элементов Число элементов, содержащихся в массиве. Элементы в массиве непосредственно связаны с индексом массива. В Visual Basic .NET первый индекс массива всегда 0.
    Совет. Массивы, которые содержат заданное число элементов, называются массивами фиксированной длины или массивами с фиксированными границами. Массивы, которые содержат переменное число элементов (массивы, которые при работе программы могут расширяться), называются динамическими массивами.

    Объявление массива фиксированной длины

    Базовый синтаксис открытого массива фиксированной длины такой:

    Dim Имя_массива(объявление_индекса1, объявление_индекса 2, ...) As тип_данных

    Здесь важную роль играют следующие аргументы.

  • Dim - это ключевое слово, которое объявляет массив. Если вы помещаете массив в стандартный модуль, то используйте вместо него слово Public.
  • Имя_массива - это имя переменной массива.
  • объявление_индекса1 - это верхняя граница первого измерения массива, которая равняется количеству элементов минус 1.
  • объявление_индекса2 - это верхняя граница второго измерения массива, которая равняется количеству элементов минус 1. (Через запятую можно добавлять дополнительные измерения массива.)
  • тип_данных - это ключевое слово, соответствующее типу данных, которые будут содержаться в этом массиве.
  • Например, чтобы объявить одномерный строковый массив с именем Employees, которые может хранить 10 имен сотрудников (пронумерованных от 0 до 9), необходимо ввести в процедуре события следующую строку:

    Dim Employees(9) As String

    В стандартном модуле это же объявление массива будет выглядеть так:

    Public Employees(9) As String

    Когда вы создаете массив, Visual Basic выделяет для него место в памяти. На следующей иллюстрация показана концепция организации массива. 10 элементов массива пронумерованы от 0 до 9, а не от 1 до 10, так как индексы массива всегда начинаются с 0. (Оператор Option Base из Visual Basic 6, который позволял вам индексировать массивы, начиная с 1, больше не поддерживается.)

    Чтобы объявить открытый двумерный массив с именем Scoreboard, который может хранить две строки и девять столбцов данных типа короткого целого, нужно ввести в процедуре события или в верхней части формы такой оператор:

    Dim Scoreboard(1, 8) As Short

    Когда вы создаете двумерный массив, Visual Basic выделяет для него место в памяти. Затем вы можете использовать этот массив в вашей программе так, как будто это таблица значений, как показано на следующей иллюстрации. (В этом случае элементы массива пронумерованы от 0 до 1 и от 0 до 8.)

    Работа с элементами массива

    После того, как вы объявили массив с помощью ключевого слова Dim или Public, его можно использовать в вашей программе. Для ссылки на элемент массива используются имя массива и индекс массива, заключенный в круглые скобки. Индекс должен быть целым числом или выражением, которое при его вычислении дает в результате целое число. Например, индекс может быть числом 5, целочисленной переменной num или выражением типа "num - 1". (Часто используется переменная-счетчик цикла For $$\dots$$ Next.) Следующий оператор присваивает элементу с индексом 5 массива Employees, использовавшегося в предыдущем разделе, значение "Лесли":

    Employees(5) = "Лесли"

    В нашем массиве Employees это приведет к следующему результату.

    Аналогично следующий оператор присваивает элементу, расположенному в строке 0 и столбце 2 (начало третьей подачи) массива Scoreboard, приведенного в предыдущем разделе, значение 4:

    Scoreboard(0, 2) = 4

    В нашем массиве Scoreboard это приведет к следующему результату.

    Эту методику индексирования можно использовать для присвоения и получения значений элементов массива.

    Создание массива фиксированной длины для хранения температур

    В следующем упражнении одномерный массив с именем Temperatures используется для записи максимальных ежедневных температур в течение недели. Эта программа демонстрирует, как можно использовать массив для хранения и обработки группы связанных значений в форме. Переменная массива Temperatures объявляется в верхней части формы, а затем с помощью функции InputBox в цикле For $$\dots$$ Next (см. лекцию 7) этому массиву присваиваются температуры. Для указания каждого из элементов массива используется счетчик цикла. Затем с помощью цикла For $$\dots$$ Next и объекта текстового поля содержимое массива отображается в форме. Также вычисляется и отображается "средняя" максимальная температура.

    Функции LBound и UBound

    Для облегчения работы с массивом программа Fixed Array использует для проверки верхней границы (старшего индекса) массива функцию UBound. UBound - это старое ключевое слово BASIC и Visual Basic, которое используется до сих пор; оно позволяет обрабатывать массивы, не изучая операторов объявления, которые содержат точные указания на то, сколько элементов содержится в массиве. Тесно связанная с ней функция LBound, которая проверяет нижнюю границу массива, в Visual Basic .NET все еще присутствует, но так как все массивы Visual Basic .NET теперь имеют нижнюю границу, равную 0, эта функция просто возвращает нулевое значение. Функции UBound и LBound имеют следующий синтаксис

    LBound(Имя_массива)
    UBound(Имя_массива)

    где Имя_массива - это имя массива, которое было объявлено в проекте.

    Массив фиксированной длины

  • Запустите Microsoft Visual Studio и создайте в папке c:\vbnet03sbs\ Гл.11 новый проект с именем My Fixed Array.
  • Нарисуйте в форме текстовое поле.
  • Установите свойство Multiline объекта TextBox1 на значение True, чтобы можно было изменить размер этого объекта.
  • Измените размер объекта текстового поля так, чтобы он заполнял почти все пространство формы.
  • Нарисуйте в форме под этим объектом текстового поля два широких объекта кнопок, расположенных рядом друг с другом.
  • Установите для формы и ее объектов следующие свойства.

    Объект Свойство Установка
    TextBox1 ScrollBars Vertical
    Text пустой (empty)
    Button1 Text "Ввести температуры"
    Button2 Text "Отобразить температуры"
    Form1 Text "Фиксированный массив температур"

    Ваша форма должна выглядеть примерно так.

  • Чтобы просмотреть Редактор кода, щелкните в Обозревателе решений на кнопке View Code (Просмотреть код).
  • Прокрутите программный код формы в самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующее объявление массива:

    Dim Temperatures(6) As Single

    Этот оператор создает массив с именем Temperatures (имеющий тип Single ), который содержит семь элементов, пронумерованных от 0 до 6. Так как этот массив был объявлен в верхней части формы, он будет доступен во всех процедурах событий формы.

  • Снова отобразите форму, а затем щелкните дважды на кнопке Ввести температуры ( Button1 ). В Редакторе кода появится процедура события Button1_Click.
  • Чтобы запросить у пользователя температуры и загрузить ввод в массив, введите следующие операторы программы:

    Dim Prompt, Title As String
    Dim i As Short
    Prompt = "Введите максимальную температуру за день."
    For i = 0 To UBound(Temperatures)
      Title = "День "  (i + 1)
      Temperatures(i) = InputBox(Prompt, Title)
    Next

    При загрузке температур в элементы массива с 0 по 6 цикл For...Next использует в качестве индекса массива переменную-счетчик типа Short с именем i. Вместо того чтобы использовать простой синтаксис цикла For

    For i = 0 to 6

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

    For i = 0 To UBound(Temperatures)

    определяет верхнюю границу массива с помощью оператора UBound. Это методика достаточно гибкая; если в дальнейшем массив увеличится или уменьшится, цикл For автоматически подстроится под новый размер массива.

    Чтобы заполнить массив температурами, процедура события использует функцию InputBox, которая отображает текущую дату с помощью счетчика цикла For.

  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на кнопке Отобразить температуры ( Button2 ).
  • Введите в процедуре события Button2_Click операторы программы:

    Dim Result As String
    Dim i As Short
    Dim Total As Single = 0
    Result = "Максимальные температуры за неделю: "  vbCrLf  vbCrLf
    For i = 0 To UBound(Temperatures)
      Result = Result  "День "  (i + 1)  vbTab  _
      Temperatures(i)  vbCrLf
      Total = Total + Temperatures(i)
    Next
    Result = Result  vbCrLf  _
    "Средняя температура: "  Format(Total / 7, "0.0")
    TextBox1.Text = Result

    Эта процедура события использует цикл For $$\dots$$ Next для перебора элементов массива, и добавляет содержимое каждого из элементов в строковую переменную с именем Result, которая объявлена в верхней части процедуры события. Для того чтобы добавить в эту строковую переменную символ перевода строки ( vbCrLf ), символы табуляции ( vbTab ) и заголовки, я использовал несколько литеральных констант, специальных констант и оператор конкатенации строк (). Константа vbCrLf, использованная здесь впервые, содержит символ перевода строки и символ возврата каретки, и является эффективным способом создавать новые строки. Константа vbTab также используется здесь впервые и создает в строке Result между днем и значением температуры некоторое расстояние. В конце процедуры события определяется среднее значение для всех температур, и окончательная строка присваивается свойству Text объекта текстового поля:

    TextBox1.Text = Result
  • Чтобы сохранить проект, щелкните на кнопке Save All (Сохранить все) на стандартной панели инструментов.
  • Чтобы запустить программу, щелкните на кнопке Start (Начать).

    Примечание. Готовая программа Fixed Array лежит в папке c:\vbnet03sbs\Гл.11\fixed array.
  • Щелкните на кнопке Ввести температуры, а затем при появлении запросов от функции InputBox введите семь различных температур. Диалоговое окно функции InputBox выглядит так.

  • После того, как вы введете температуры, щелкните на кнопке Отобразить температуры. Visual Basic отобразит все температуры в текстовом поле и напечатает внизу их среднее значение. Ваш экран должен выглядеть примерно так.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Создание динамического массива

    Массивы удобны для работы со списками чисел, особенно если вы обрабатываете их с помощью циклов For $$\dots$$ Next. Но что, если при запуске программы вы не знаете, сколько места в массиве вам понадобится? Например, если нужно, чтобы пользователь выбирал, сколько температур вводить в программу Fixed Array?

    Visual Basic эффективно решает эту проблему с помощью специального "эластичного" контейнера, который называется динамическим массивом. Размерность динамических массивов определяется во время работы программы - либо тогда, когда пользователь указывает размер этого массива, либо когда логика программы определяет размер массива на основе некоторых условий. Выделение места под динамический массив требует нескольких действий. Хотя размер массива и не будет указан до тех пор, пока программа не будет запущена, при проектировании необходимо зарезервировать для него некоторые объем. Чтобы создать динамический массив, выполните такие базовые действия.

  • При разработке программы укажите имя и тип массива, не указывая при этом числа элементов этого массива. Например, чтобы создать динамический массив с именем Temperatures, введите

    Dim Temperatures() As Single
  • Добавьте код для определения числа элементов, которые должны быть в массиве во время выполнения программы. Вы можете запросить это число у пользователя с помощью функции InputBox, или вычислить необходимый объем с помощью свойств или другой логики. Например, следующие операторы получают размер массива от пользователя и присваивают его короткой целочисленной переменной Days:

    Dim Days As Short
    Days = InputBox("Сколько дней?", "Создание массива")
  • Чтобы задать размерность массива, используйте переменную в операторе ReDim (вычтите 1, так как массивы нумеруются с 0). Например, следующий оператор устанавливает размер массива Temperatures при выполнении программы с помощью переменной Days:

    ReDim Temperatures(Days - 1)
  • Единственным ограничением при использовании ReDim является то, что вы не должны пытаться изменить число измерений массива, который был объявлен ранее.
  • В цикле For $$\dots$$ Next для определения верхней границы массива используйте функцию UBound и произведите требуемую обработку массива, как показано здесь:

    For i = 0 to UBound(Temperatures)
      Temperatures(i) = InputBox(Prompt, Title)
    Next
  • В следующем упражнении вы будете использовать эти шаги для доработки программы Fixed Array так, что она с помощью динамического массива сможет обрабатывать любое количество температур.

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

  • Чтобы отобразить код программы проекта Fixed Array, откройте Редактор кода.
  • Прокрутите его вверх до начала кода формы, в которой вы первоначально объявили фиксированный массив Temperatures.
  • Удалите число 6 из объявления массива Temperatures, чтобы массив стал динамическим. Этот оператор должен выглядеть так:

    Dim Temperatures() As Single
  • Добавьте под объявлением массива Temperatures следующее объявление переменной:

    Dim Days As Integer

    Целочисленная переменная Days будет использована для получения ввода от пользователя и для задания размера динамического массива во время выполнения.

  • Прокрутите Редактор кода вниз, чтобы отобразить процедуру события Button1_Click, и измените ее код так, как показано ниже.

    Dim Prompt, Title As String
    Dim i As Short
    Prompt = "Введите максимальную температуру за день."
    Days = InputBox("Сколько дней?", "Создание массива")
    If Days > 0 Then ReDim Temperatures(Days - 1)
    For i = 0 To UBound (Temperatures)
      Title = "День "  (i + 1)
    Temperatures(i) = InputBox(Prompt, Title)
    Next

    Четвертая и пятая строки запрашивают у пользователя количество температур, которые надо сохранить, а затем этот ввод используется для задания размера динамического массива. Оператор If...Then используется для того, чтобы проверить, что число дней больше 0. (Задание размера массива с помощью числа, которое меньше 0, приведет к возникновению ошибки.) Так как для хранения температуры для первого дня используется индекс 0 массива, переменная Days при задании размера массива уменьшается на 1. Переменная Days не нужна для определения верхней границы в цикле For $$\dots$$ Next - как и в предыдущем примере, вместо этого используется функция UBound.

  • Прокрутите Редактор кода вниз, чтобы отобразить процедуру события Button2_Click. Измените ее код так, как показано в следующем фрагменте кода. (Измененные элементы выделены жирным.)

    Dim Result As String
    Dim i As Short
    Dim Total As Single = 0
    Result = "Максимальные температуры:"  vbCrLf  vbCrLf
    For i = 0 To UBound(Temperatures)
      Result = Result  "День "  (i + 1)  vbTab  _
      Temperatures(i)  vbCrLf
      Total = Total + Temperatures(i)
    Next
    Result = Result  vbCrLf  _
    "Средняя температура: "  Format(Total / Days, "0.0")
    TextBox1.Text = Result

    Переменная Days заменяет число 7 при вычислении средней температуры в нижней части этой процедуры события. Я также отредактировал заголовок "Максимальные температуры", который отображается в текстовом поле.

  • Сохраните изменения на диск.

    Примечание. На прилагаемом компакт-диске я дал этому проекту отдельное имя, чтобы отделить его от проекта Fixed Array. Готовая программа Dynamic Array лежит в папке c:\vbnet03sbs\ Гл.11\dynamic array.
  • Чтобы запустить программу, щелкните на кнопке Start (Начать).
  • Щелкните на кнопке Ввести температуры.
  • Когда увидите запрос на число дней, для которых вы хотите записать температуры, введите 5 и нажмите на OK.
  • Когда вас попросят ввести температуры, введите пять температур.
  • После того, как вы закончите вводить температуры, щелкните на кнопке Отобразить температуры. Программа отобразит в форме пять температур, а также их среднее значение. Ваш экран должен выглядеть примерно так.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Защита содержимого массива с помощью ReDim Preserve

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

    К счастью Visual Basic .NET предоставляет такую же полезную функцию для изменения размера массива, которую предоставлял и Visual Basic 6: ключевое слово Preserve, которое можно использовать для сохранения данных в массиве при изменении его размера. Синтаксис ключевого слова Preserve имеет следующий вид:

    ReDim Preserve Имя_массива(размер1, размер2, ...)

    В таком операторе изменения размера массив должен иметь такое же количество измерений и содержать тот же самый тип данных. В дополнение к этому существует дополнительное ограничение, состоящее в том, что вы можете изменить размер только последнего измерения массива. Например, если массив имеет два или более измерений, вы можете изменить размер только последнего измерения и сохранить при этом содержимое массива. (Одномерные массивы автоматически проходят этот тест, так что вы спокойно можете расширять размер таких динамических массивов с помощью ключевого слова Preserve.)

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

    Если вы с помощью следующей записи объявили динамический строковый массив с именем Philosophers:

    Dim Philosophers() As String

    измените его размер и добавьте в него данные с помощью кода, аналогичного следующему:

    ReDim Philosophers(200)
    Philosophers(200) = "Стив Гаррисон"

    Можно увеличить размер массива Philosophers до 301 элемента (0-300) и сохранить существующее содержимое с помощью следующей записи:

    ReDim Preserve Philosophers(300)

    Более сложный пример, включающий трехмерный массив, использует аналогичный синтаксис. Представьте, что вы используете в вашей программе трехмерный массив с именем myCube для хранения чисел с плавающей точкой одинарной точности. Массив myCube можно объявить с помощью следующей конструкции:

    Dim myCube(,,) As Single

    Затем можно изменить размер массива и добавить в него данные с помощью следующего кода:

    ReDim myCube(25, 25, 25)
    myCube(10, 1, 1) = 150.46

    после чего увеличить размер третьего измерения массива (сохранив при этом содержимое массива) с помощью следующей записи:

    ReDim Preserve myCube(25, 25, 50)

    Однако в этом примере может быть расширено только третье измерение - первое и второе измерения не могут быть изменены, если вы изменяете размер массива с помощью ключевого слова Preserve. Попытка изменить размер первого или второго измерений в этом примере приведет при выполнении оператора ReDim Preserve к ошибке времени исполнения.

    Немного поэкспериментируйте с ReDim Preserve и посмотрите, как вы можете его использовать, чтобы сделать ваши собственные массивы более гибкими и удобными.

    На этом работа с массивами пока закончена. В остальной части этой лекции речь пойдет о коллекциях.

    Работа с коллекциями объектов

    В предыдущем разделе вы узнали об использовании массивов для хранения информации при выполнении программы. В этом разделе вы изучите коллекции - еще один метод работы с объектами элементов управления и другими данными в программах на Visual Basic. Вы уже знаете, что объекты в форме хранятся вместе в одном и том же файле. Но знаете ли вы о том, что Visual Basic рассматривает эти объекты как члены одной и той же группы? В терминологии Visual Basic весь набор объектов формы называется коллекцией элементов управления ( Controls ). Коллекция Controls создается автоматически при создании новой формы, и когда вы добавляете в форму новые объекты, они автоматически становятся частью этой коллекции. На самом деле Visual Basic поддерживает несколько стандартных коллекций объектов, которые можно использовать в программах. Далее вы узнаете о базовых приемах работы с любыми попадающимися вам коллекциями.

    Каждая коллекция в программе имеет свое собственное имя, таким образом, вы можете ссылаться на нее как на отдельный элемент кода программы. Например, коллекция, содержащая все объекты формы, называется коллекцией Controls. Если в вашем проекте более одной формы, то чтобы различать коллекции Controls, относящиеся к этим формам, вы можете создать и использовать открытые переменные, ассоциированные с именами форм. (Об использовании открытых переменных для хранения данных форм вы узнаете в лекции 15) Вы можете добавлять элементы управления в коллекцию Controls формы даже программно.

    В дополнение к тому, что Visual Studio позволяет вам работать с объектами и коллекциями в ваших собственных программах, она еще позволяет просматривать вашу систему в поисках объектов других приложений и использовать их в ваших программах. Мы снова вернемся к этому вопросу в лекции 13 при изучении Visual Studio Object Browser (Обозревателя объектов).

    Ссылка на объекты в коллекции

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

    Controls(0).Text = "Бизнес"

    Этот оператор устанавливает свойство Text последнего объекта формы на значение "Бизнес". (Второй от конца созданный объект имеет индекс 1, третий от конца объект - индекс 2, и т.д.) Учитывая эту логику важно, чтобы вы никогда не связывали конкретный объект формы со значением индекса - если в коллекцию будет добавлен новый объект, этот новый объект получит индекс 0, а остальные индексы объектов увеличатся на 1.

    Следующий цикл For...Next отображает с помощью окна сообщения имена последних четырех добавленных в форму элементов управления:

    Dim i As Integer
    For i = 0 To 3
      MsgBox(Controls(i).Name)
    Next i

    Я указал этому циклу перебирать значения от 0 до 3, так как последний добавленный в форму элемент управления находится по индексу "0". В следующем разделе вы изучите более эффективный метод написания такого цикла.

    Написание циклов For Each ... Next

    Хотя на члены коллекции можно ссылаться индивидуально, наиболее эффективный способ работы с объектами в коллекциях - обрабатывать их как группы. На самом деле причиной существования коллекций является то, что вы, таким образом, можете более эффективно обрабатывать группы объектов: отобразить, переместить, отсортировать или изменить размер целой коллекции объектов одновременно.

    Чтобы выполнить эту задачу, вы можете использовать для последовательного перебора объектов в коллекции специальный цикл For Each...Next. Цикл For Each...Next аналогичен циклу For $$\dots$$ Next. Когда цикл For Each...Next используется вместе с коллекцией Controls, он выглядит так:

    Dim CtrlVar As Control
    ...
    For Each CtrlVar In Controls
      обработка объекта
    Next CtrlVar

    Переменная CtrlVar объявлена как переменная типа Control и представляет текущий объект коллекции. Controls (обратите внимание на конечную "s") - это класс коллекции, который представляет все объекты элементов управления текущей формы. Тело цикла используется для обработки отдельных объектов этой коллекции. Например, можно изменить свойства Enabled, Left, Top, Text или Visible объектов коллекции, или создать список имен всех объектов и поместить его в поле списка.

    Переменная CtrlVar представляет текущий объект цикла For Each...Next.

    Эксперименты с объектами из коллекции Controls

    В следующих упражнениях вы будете использовать код программы для манипуляций объектами на форме с помощью коллекции Controls. Ваш проект будет иметь три объекта кнопок, и вы создадите процедуры событий, которые будут изменять свойства Text каждого из этих объектов, перемещать объекты вправо и специальным образом обрабатывать один из объектов группы. Для манипуляций с объектами при щелчках пользователя на кнопках программа будет использовать три цикла For Each...Next.

    Использование цикла For Each ... Next для изменения свойств Text

  • Чтобы закрыть текущий проект, щелкните на команде Close Solution (Закрыть решение) в меню File (Файл).
  • В папке c:\vbnet03sbs\Гл.11 создайте новый проект Windows Application (Приложение Windows) на Visual Basic с именем My Controls Collection.
  • Используйте элемент управления Button и нарисуйте в левой части формы три объекта кнопок, как показано ниже.

  • С помощью окна Properties (Свойства) установите свойство Name третьего объекта кнопки ( Button3 ) на значение btnMoveObjects.
  • Сделайте на объекте первой кнопки ( Button1 ) формы двойной щелчок мышью. В Редакторе кода появится процедура события Button1_Click.
  • Введите следующие операторы программы:

    For Each ctrl In Controls
      ctrl.Text = "Нажми меня!"
    Next

    Это цикл For Each...Next перебирает коллекцию Controls формы по одному элементу управления и устанавливает свойство каждого из объектов на значение "Нажми меня!". В качестве переменной объекта цикл использует ctrl, которую вы объявите в следующем шаге.

  • Прокрутите программный код формы на самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующие комментарий и объявление переменной:

    ' Объявление переменной типа Control для представления элементов
    ' управления формы
    Dim ctrl As Control

    Это объявление глобальной переменной создает переменную типа Control, которая будет представлять в программе текущие элементы управления формы. Вы объявляете эту переменную в общей области объявлений формы, так что она будет доступна во всех процедурах событий этой формы. Теперь запустите программу и измените свойство Text для каждой кнопки формы.

  • Чтобы запустить программу, щелкните на кнопке Start (Начать), расположенной на стандартной панели инструментов.
  • Щелкните на первой кнопке ( Button1 ) формы. Процедура события Button1_Click изменяет свойство Text для каждого элемента управления из коллекции Controls. Ваша форма будет выглядеть примерно так.

  • Щелкните на кнопке Закрыть формы. Программа закроется. Теперь можно провести еще один эксперимент с коллекцией Controls. Используйте свойство Left для перемещения каждого элемента управления из коллекции Controls вправо.
  • Использование цикла For Each ... Next для перемещения элементов управления

  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на объекте второй кнопки ( Button2 ). Введите в процедуре события Button2_Click следующий код программы:

    For Each ctrl In Controls
      ctrl.Left = ctrl.Left + 25
    Next

    Каждый раз, когда пользователь будет щелкать на второй кнопке, этот цикл For Each...Next будет перебирать объекты в коллекции Controls и перемещать их на 25 пикселей вправо. (Чтобы переместить объекты на 25 пикселей влево, нужно вычитать 25.) Пиксель - это не зависящая от устройства единица измерения, которая позволяет точно расположить объекты в форме.

    Совет. В Visual Basic 6 для указания таких измерений вместо пикселей обычно использовались "твипы" (twips). За информацией о преобразовании существующего кода Visual Basic 6 с использованием измерения в твипах в код с использованием пикселей обратитесь к справочной системе Visual Studio и найдите в ней заголовок "ScaleMode Is Not Supported" ( ScaleMode не поддерживается).
  • Как видно из введенной выше процедуры события, переменная ctrl обозначает текущий объект в коллекции и содержит те же установки свойств, что и представляемый ею объект. В этом цикле вы изменяете свойство Left, которое определяет положение объекта относительно левой границы формы.
  • Щелкните на кнопке Start (Начать) стандартной панели инструментов. Программа запустится и в левой части формы появится три кнопки.
  • Щелкните несколько раз на второй кнопке. Каждый раз, когда вы щелкаете на этой кнопке, объекты перемещаются вправо. После пяти щелчков ваш экран будет выглядеть примерно так, как показано на рисунке вверху следующей страницы.
  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Перемещение всех объектов формы, конечно, необязательно. Visual Basic позволяет обрабатывать члены коллекции и по отдельности. В следующем упражнении вы узнаете о том, как при перемещении двух объектов кнопок вправо сохранить положение третьей кнопки неизменным.

    Использование свойства Name в цикле For Each ... Next

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

    Чтобы использовать свойство Name подобным образом, выделите объекты, которые вы хотите обработать, а затем отметьте их свойства Name. При переборе объектов формы в цикле For Each...Next используйте необходимое количество операторов If для проверки важного свойства Name, и обработайте эти объекты особым способом. Например, предположим, что вы хотите создать цикл For Each...Next, который перемещает объект по форме медленнее, чем все остальные объекты. Можно использовать оператор If...Then для нахождения свойства Name медленного объекта, а затем перемещать этот объект на более короткие дистанции, увеличивая его свойство Left не так сильно, как вы делаете это для других объектов.

    Совет. Если вы планируете использовать в цикле For Each...Next специальную обработку для нескольких объектов, то вместе с оператором If...Then вы можете использовать операторы ElseIf или структуру выбора Select Case.

    В следующем упражнении вы будете проверять свойство Name третьего объекта кнопки ( btnMoveObjects ) и обрабатывать ее в цикле For Each...Next особым образом. В конечном счете, вы получите процедуру события, которая перемещает вправо первые две кнопки, но оставляет на месте третью кнопку.

    Совет. В дополнение к свойству Name большинство объектов имеют свойство Tag. Аналогично свойству Name свойство Tag - это место, где можно сохранять строковые данные касающиеся объекта. Свойство Tag по умолчанию пусто, но вы можете присвоить ему некую информацию и проверять ее для однозначной идентификации объектов вашей программы, которые вы хотите обрабатывать особым образом.

    Использование свойства Name для специальной обработки элемента управления из коллекции Controls

  • Отобразите форму, а затем сделайте двойной щелчок мышью на объекте третьей кнопки. В Редакторе кода появится процедура события btnMoveObjects_Click. Помните, что в предыдущем примере вы изменили свойство Name этого объекта с Button3 на btnMoveObjects.
  • Введите в этой процедуре события следующий код программы:

    For Each ctrl In Controls
      If ctrl.Name <> "btnMoveObjects" Then
        ctrl.Left = ctrl.Left + 25
      End If
    Next

    Новой функцией этого цикла For Each...Next является оператор If...Then, который проверяет каждый член коллекции и смотрит, не равно ли его свойство Name значению btnMoveObjects. Если цикл находит этот маркер, он пропускает объект, не перемещая его. Заметьте, что, как и в предыдущем примере, переменная ctrl была объявлена в верхней части формы как переменная типа Control с областью видимости, распространяющейся на всю форму.

  • Щелкните на кнопке Save All (Сохранить все) стандартной панели инструментов.
  • Щелкните на кнопке Start (Начать). Программа запустится, и в форме появятся три объекта ее интерфейса.

    Примечание. Готовая программа Controls Collection расположена в папке c:\vbnet03sbs\Гл.11\controls collection.
  • Щелкните шесть или семь раз на третьем объекте кнопки. Каждый раз при щелчке на этой кнопке объекты формы перемещаются по экрану. Однако третья кнопка остается на своем месте, как показано на следующем рисунке.

    Специальная обработка одного объекта в коллекции может быть очень полезна. В этом случае использование свойства Name в цикле For Each...Next улучшает читаемость кода программы, предлагая многочисленные способы применения его для игр и графических программ. Когда вы будете использовать остальные типы коллекций Visual Basic, не забывайте о свойстве Name.

  • Чтобы завершить выполнение программы, щелкните на кнопке Закрыть формы.
  • Создание собственных коллекций

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

    Новые коллекции объявляются в программе как переменные, и место, в котором вы их объявляете, определяет их область видимости, или область, в которой они сохраняют свои значения. Так как коллекции очень полезны, я обычно объявляю их в верхней части формы или в стандартном модуле. Новые объявления коллекций требуют записи

    Dim Имя_коллекции  As New Collection()

    где Имя_коллеции - это имя вашей коллекции. Если вы помещаете объявление коллекции в стандартном модуле, то вместо ключевого слова Dim следует использовать ключевое слово Public. После того, как вы создали коллекцию, с помощью метода Add в нее можно добавить ее члены, и узнать содержимое отдельных ее членов с помощью цикла For Each...Next.

    В следующем упражнении показано, как создать коллекцию для хранения строковых данных, представляющих интернет-адреса (URL), которые вы недавно использовали. Для соединения с сетью программа будет использовать метод Visual Basic с именем System.Diagnostics.Process.Start и ваш веб-браузер по умолчанию.

    Хранение интернет-адресов с помощью коллекции

  • Щелкните на команде Close Solution (Закрыть решение) в меню File (Файл). Текущий проект закроется.
  • В папке c:\vbnet03sbs\Гл.11 создайте новый проект на Visual Basic с именем My URL Collection.
  • В верхней части формы нарисуйте широкий объект текстового поля, отцентрированный по горизонтали.
  • В форме под этим объектом текстового поля нарисуйте два широких объекта кнопок, расположенных одна под другой.
  • Установите для формы и ее объектов следующие свойства:

    Объект Свойство Установка
    TextBox1 Text http://www.microsoft.com/mspress
    Button1 Text "Посетить сайт"
    Button2 Text "Создать список посещенных сайтов"
    Form1 Text "Коллекция URL"
  • Ваша форма должна выглядеть примерно так.

  • Чтобы отобразить Редактор кода, щелкните в Обозревателе решений на кнопке View Code (Просмотреть код).
  • Прокрутите программный код формы в самый верх, и прямо под тэгом "Windows Form Designer generated code" ("Код, автоматически созданный конструктором форм Windows") введите следующее объявление переменной:

    Dim URLsVisited As New Collection()

    Этот оператор создает новую коллекцию и присваивает ее переменной с именем URLsVisited. Так как вы расположили это объявление в верхней части формы, коллекция будет иметь область видимости, распространяющуюся на все процедуры событий формы.

  • Снова отобразите форму, сделайте двойной щелчок мышью на кнопке Посетить сайт, а затем введите в процедуре события Button1_Click следующий код:

    URLsVisited.Add(TextBox1.Text)
    System.Diagnostics.Process.Start(TextBox1.Text)

    Этот код программы использует метод Add для заполнения коллекции ее членами. Когда пользователь щелкает на объекте Button1, программа полагает, что в объект TextBox1 был введен правильный интернет-адрес. Каждый раз при щелчке на объекте Button1 текущий URL из TextBox1 копируется как строка в коллекцию URLsVisited. Далее вызывается метод System.Diagnostics.Process.Start с этим URL в качестве параметра. Так как параметр представляет собой URL, метод Start пытается открыть этот URL с помощью веб-браузера системы по умолчанию. (Если URL некорректен или соединение с интернетом не может быть установлено, то ошибку будет обрабатывать веб-браузер.)

    Примечание. Программа добавляет в коллекцию URLsVisited только те URL, которые вы указали в объекте TextBox1. Если вы переходите на дополнительные веб-сайты с помощью собственно браузера, эти сайты не будут добавлены в коллекцию. (О комплексном способе отслеживания веб-сайтов с помощью объектной модели Internet Explorer см. лекцию 21.)
  • Снова отобразите форму, а затем сделайте двойной щелчок мышью на кнопке Создать список посещенных сайтов.
  • Введите в Редакторе кода следующий код программы:

    Dim URLName, AllURLs As String
    For Each URLName In URLsVisited
      AllURLs = AllURLs  URLName  vbCrLf
    Next URLName
    MsgBox(AllURLs, MsgBoxStyle.Information, "Посещенные сайты")

    Эта процедура события с помощью цикла For Each...Next и функции MsgBox печатает всю коллекцию. Этот код объявляет строковую переменную с именем URLName, которая хранит каждый из членов коллекции при его обработке, а его значение с помощью оператора конкатенации () и строковой константы vbCrLf добавляется в строку с именем AllURLs.

    Наконец, строка AllURLs, которая представляет всю коллекцию URLsVisited, отображается в окне сообщения. Я добавил к функции MsgBox аргумент MsgBoxStyle.Information, чтобы подчеркнуть, что отображаемый текст является общей информацией, а не предупреждением. ( MsgBoxStyle.Information также является встроенной константой Visual Basic.)

  • Чтобы сохранить изменения, щелкните на кнопке Save All (Сохранить все).
  • Примечание. Чтобы запустить программу URL Collection, ваш компьютер должен установить соединение с интернетом и иметь установленный веб-браузер, такой, как Microsoft Internet Explorer или Netscape Navigator.

    Запуск программы URL Collection

  • Чтобы запустить программу, щелкните на кнопке Start (Начать).

    Примечание. Готовая программа Collection лежит в папке c:\vbnet03sbs\Гл.11\url collection.

    Утилита содержит в текстовом поле URL адрес веб-сайта по умолчанию, так что при первом запуске вам не требуется вводить ваш собственный интернет-адрес.

  • Щелкните на кнопке Посетить сайт. Visual Basic добавит в коллекцию ), а затем откроет веб-браузер вашей системы по умолчанию и загрузит требуемую страницу, как показано на рисунке вверху следующей страницы. Если вам интересно, изучите содержимое этого веб-сайта.
  • Снова щелкните на форме. (Возможно, нужно будет щелкнуть на значке на панели задач Windows.)

  • Щелкните на кнопке Создать список посещенных сайтов. Visual Basic исполняет процедуру события для объекта Button2. Вы увидите такое окно сообщения.

  • Щелкните в окне сообщения на ).
  • Посетите еще несколько веб-сайтов с помощью формы Коллекция URL, а затем щелкните на кнопке Создать список посещенных сайтов. Каждый раз, когда вы щелкаете на кнопке Создать список посещенных сайтов, функция MsgBox расширяется для показа растущего списка URL, как показано ниже.

    Если вы посетили более десятка веб-сайтов, то вам понадобится заменить функцию MsgBox многострочным текстовым полем в форме.

  • Когда закончите, щелкните на кнопке Закрыть формы, а затем закройте веб-браузер.
  • Поздравляем! Вы узнали, как использовать коллекцию Controls и создавать новые коллекции и как обрабатывать их с помощью цикла For Each...Next. Эти навыки будут полезны всегда, когда вы будете работать с коллекциями.

    Следующий шаг: коллекции Visual Basic for Applications

    Если в будущем вы решите написать макросы Visual Basic для приложений Microsoft Office, то обнаружите, что в объектных моделях Microsoft Word, Microsoft Excel, Microsoft Access, Microsoft PowerPoint и некоторых других приложений, которые поддерживают язык программирования Visual Basic for Applications, коллекции играют очень важную роль. Например, в Word все открытые документы текстового процессора хранятся в коллекции Documents, а каждый параграф текущего документа - в коллекции Paragraphs. Вы можете манипулировать этими коллекциями с помощью цикла For Each...Next точно так же, как вы делали это с другими коллекциями из предыдущих примеров.

    Например, следующий пример кода является частью макроса Word 2002, который использует цикл For Each...Next для проверки каждого открытого документа из коллекции Documents на предмет имени файла MyLetter.doc. Если этот файл в коллекции найден, макрос сохраняет его с помощью метода Save. Если файл в коллекции не найден, макрос пытается открыть этот файл из папки My Documents, расположенной на диске C.

    Dim aDoc As Object
    Dim docFound As Boolean
    Dim docLocation As String
    docFound = False
    docLocation = "c:\my documents\myletter.doc"
    For Each aDoc In Documents
      If InStr(1, aDoc.Name, "myletter.doc", 1) Then
        docFound = True
        aDoc.Save
        Exit For
      End If
    Next aDoc
    If docFound = False Then
      Documents.Open FileName:=docLocation
    End If
    Совет. Этот пример макроса для Word 2002 демонстрирует, как можно использовать коллекции в Visual Basic for Applications, но этот исходный код разработан для Word, а не для компилятора Visual Basic. Чтобы его проверить, необходимо запустить Word, щелкнуть на команде Macros (Макросы:) из подменю Macro (Макрос) меню Tools (Сервис), создать новое имя для макроса, а затем ввести этот код с помощью специального редактора макросов Word. (Если вы не находитесь в Word, то коллекция Documents не будет иметь для компилятора никакого смысла.)

    Макрос начинается с объявления трех переменных. Объектная переменная aDoc представляет текущий элемент коллекции в цикле For Each...Next. Переменной Boolean с именем docFound будет присвоено логическое значение True, если документ в коллекции Documents найден. Строковая переменная docLocation будет содержать путь файла MyLetter.doc на диске. (Эта процедура предполагает, что файл MyLetter.doc находится в папке My Documents на диске C.)

    Цикл For Each...Next перебирает все документы в коллекции Documents и ищет файл MyLetter. Если файл с помощью функции InStr (которая ищет одну строку в другой) обнаружен, то файл сохраняется. Если файл не найден, макрос пытается открыть его с помощью метода Open объекта Documents. Также обратите внимание на оператор Exit For, который используется для выхода из цикла For Each...Next, когда файл MyLetter найден и сохранен на диск. Exit For - это специальный оператор программы, который можно использовать для выхода из циклов For...Next или For Each...Next, когда продолжение их работы становится нежелательным. В нашем примере, если файл MyLetter.doc в коллекции уже найден, продолжение поиска будет безрезультатно. Здесь оператор Exit For предоставляет удобный способ остановить цикл сразу, как только его задача выполнена.

    Краткая справка по лекции 11

    Чтобы Сделайте следующее
    Создать массив Задайте размерность массива с помощью ключевого слова Dim. Например: Dim Employees(9) As String
    Создать открытый массив Задайте размерность массива с помощью ключевого слова Public и разместите его объявление в стандартном модуле. Например: Public Employees(9) As String
    Поместить значение в массив Укажите имя массива, индекс элемента массива и значение. Например: Employees(5) = "Leslie"
    Отформатировать текстовую строку с использованием символов возврата каретки и табуляции Используйте в коде программы константы vbCrLf и vbTab. (Чтобы добавить эти значения, используйте оператор .)
    Создать динамический массив При объявлении укажите имя и тип массива, но не указывайте количество его элементов. (Если массив имеет несколько измерений, вставьте запятые между измерениями, но не вводите числа.) При выполнении программы укажите размер массива с помощью оператора ReDim. Например: ReDim Temperatures(10)
    Обработать элементы массива

    Напишите цикл For $$\dots$$ Next, который использует переменную-счетчик цикла для адресации каждого из элементов этого массива. Например:

    Dim i As Short
    Dim Total As Single
    For i = 0 To UBound(Temperatures)
      Total = Total + Temperatures(i)
    Next
    Изменить размер массива и сохранить в нем предыдущие данные Используйте в операторе ReDim ключевое слово Preserve. Например: ReDim Preserve myCube(25, 25, 50)
    Обработать объекты в коллекции

    Напишите цикл For Each $$\dots$$ Next, который адресует каждый член коллекции по отдельности. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      ctrl.Text = "Нажми меня!"
    Next
    Переместить объекты из коллекции Controls по экрану слева направо

    Измените в цикле For Each $$\dots$$ Next свойство Control.Left каждого из объектов коллекции. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      Ctrl.Left = Ctrl.Left + 25
    Next Ctrl
    Использовать для объекта в коллекции специальную обработку

    Проверьте с помощью цикла For Each $$\dots$$ Next свойство Name объекта из коллекции. Например:

    Dim ctrl As Control
    For Each ctrl In Controls
      If ctrl.Name <> "btnMoveObjects" Then
      ctrl.Left = ctrl.Left + 25
      End If
    Next
    Создать новую коллекцию и добавить в нее члены

    Объявите переменную с помощью записи New Collection. Для добавления членов используйте метод Add. Например:

    Dim URLsVisited As New Collection()
    URLsVisited.Add(TextBox1.Text)
    Вернуться к учебному плану