| Россия, г. Новочеркасск | 
Пользовательские компоненты
Упражнение 2. Создание невизуального компонента Planets
В этом примере мы создадим невизуальный компонент Planets, инкапсулирующий в себе названия планет Солнечной системы, и добавим его в нашу библиотеку компонентов сборки MyComponents. Названия планет будут храниться во внутреннем массиве компонента, а доступ к ним будет осуществляться через индексаторы по имени планеты или ее индексу.
- 
 В панели Solution Explorer  выделите проект MyComponents  и
    выполните команду меню Project/Add Component,
    чтобы добавить файл Planets.cs  нового
    компонента В панели Solution Explorer  выделите проект MyComponents  и
    выполните команду меню Project/Add Component,
    чтобы добавить файл Planets.cs  нового
    компонента
- 
 Дополните
      содержимое файла, автоматически сгенерированное мастером,
      следующим кодом Дополните
      содержимое файла, автоматически сгенерированное мастером,
      следующим кодом
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
    
namespace MyCompany.MyComponents
{
    public partial class Planets : Component
    {
        public Planets()
        {
            InitializeComponent();
        }
    
        public Planets(IContainer container)
        {
            container.Add(this);
    
            InitializeComponent();
        }
    }
}
    
namespace MyCompany.MyComponents
{
    partial class Planets
    {
        // Планеты
        private string[] PlanetNames ={ "Меркурий",
                                        "Венера",
                                        "Земля",
                                        "Марс",
                                        "Юпитер",
                                        "Сатурн",
                                        "Уран",
                                        "Нептун",
                                        "Плутон"
        };
    
        // Вернуть имя
        private string GetPlanetName(int index)
        {
            // Нижняя и верхняя границы массива
            int lowP = 0, highP = PlanetNames.Length - 1;
    
            // Контролирует диапазон индекса планеты и возвращает
            // ее название или генерирует исключение
            if (index < lowP || index > highP)
            {
                MessageBox.Show(String.Format("Индекс должен находиться в диапазоне {0}-{1}",
                    lowP, highP));
                index = 0;
            }
    
            return PlanetNames[index];
        }
    
        // Вернуть индекс
        private int GetPlanetPosition(string planetName)
        {
            // Сравниваем переданное имя планеты с массивом
            // PlanetNames. При несовпадении возвращаем -1 
            int result=-1;
            for(int i=0; i<PlanetNames.Length;i++)
                if (String.Compare(planetName, PlanetNames[i], true) == 0)
                {
                    result = i;
                    break;
                }
    
            return result;
        }
    
        // Свойство - индексатор: возвращает имя планеты по индексу
        public string this[int index]
        {
            get {return GetPlanetName(index); }
        }
    
        // Свойство - индексатор: возвращает индекс планеты по имени
        public int this[string planetName]
        {
            get { return GetPlanetPosition(planetName); }
        }
    
        // Свойство максимального размера массива
        public int MaxIndex
        {
            get { return PlanetNames.Length - 1; }
        }
    }
}
                            Листинг
                        24.8.
                        Расширенное содержимое файла Planets.cs   
В коде мы объявили массив с планетами и сразу инициализировали его. Создали два внутренних контролирующих метода, возвращающих название планеты по ее индексу и наоборот. Добавили два общедоступных свойства - индексатора, позволяющих работать с экземпляром компонента как с массивом, а также добавили общедоступное свойство максимального размера поля - массива с планетами.
Теперь осталось перекомпилировать сборку MyComponents.dll, в которой в одном пространстве имен MyCompany.MyComponents будут находиться уже два наших компонента, и испытать новый невизуальный компонент.
- 
 В панели Solution Explorer  вызовите контекстное меню
    для узла проекта MyComponets  и выполните команду Rebuild,
    чтобы перекомпилировать проект с компонентами В панели Solution Explorer  вызовите контекстное меню
    для узла проекта MyComponets  и выполните команду Rebuild,
    чтобы перекомпилировать проект с компонентами
- 
 Убедитесь,
    что в панели Toolbox  появился новый компонент Planets,
    который теперь можно перетаскивать на форму также, как и
    обычный библиотечный компонент Убедитесь,
    что в панели Toolbox  появился новый компонент Planets,
    который теперь можно перетаскивать на форму также, как и
    обычный библиотечный компонент
Испытание созданных компонентов
- 
 В проекте ComponentTest  настройте пользовательский
    интерфейс, как показано на рисунке и в таблице (в скобках
    приведены имена экземпляров компонентов) В проекте ComponentTest  настройте пользовательский
    интерфейс, как показано на рисунке и в таблице (в скобках
    приведены имена экземпляров компонентов)
- 
 В панели Properties  перейдите на вкладку Events  и
    создайте обработчики для элементов согласно таблицы В панели Properties  перейдите на вкладку Events  и
    создайте обработчики для элементов согласно таблицы
- 
 Заполните
    файл Form1.cs  следующим кодом Заполните
    файл Form1.cs  следующим кодом
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
    
namespace ComponentTest
{
    public partial class Form1 : Form
    {
        // Конструктор формы
        public Form1()
        {
            InitializeComponent();
    
            // Заполнение списка планетами
            for (int i = 0; i <= planets1.MaxIndex; i++)
            {
                listPlanets.Items.Add(String.Format(
                    "{0}) {1}", i, planets1[i]));
            }
    
            listPlanets.SelectedIndex = 0;
        }
    
        // Обработчики событий
        private void firstComponent1_Click(object sender, EventArgs e)
        {
            // Контролируем пустой ввод
            if (indexPlanet.Text == String.Empty) return;
    
            int index = Convert.ToInt32(indexPlanet.Text);
    
            // Контролируем максимальный индекс ввода
            index = Math.Min(index, planets1.MaxIndex);
            if (listPlanets.SelectedIndex != index)
                listPlanets.SelectedIndex = index;
            else
                MessageBox.Show(String.Format("Вы выбрали планету {0}", planets1[index]));
        }
    
        private void indexPlanet_KeyPress(object sender, KeyPressEventArgs e)
        {
            // Фильтруем цифры, Backspace, Enter (Delete и стрелки по умолчанию)
            if ((e.KeyChar < Convert.ToChar(Keys.D0) ||
                e.KeyChar > Convert.ToChar(Keys.D9))
                && e.KeyChar != Convert.ToChar(Keys.Back)
                && e.KeyChar != Convert.ToChar(Keys.Enter))
                e.Handled = true;
    
            // Реакция на клавишу Enter
            if (e.KeyChar == Convert.ToChar(Keys.Enter))
                firstComponent1_Click(null, EventArgs.Empty);
        }
    
        bool loadFlag = true; // Локальное поле-флаг
        private void listPlanets_SelectedValueChanged(object sender, EventArgs e)
        {
            int index = listPlanets.SelectedIndex;
            indexPlanet.Text = index.ToString();
            if (loadFlag)
            {
                // При первом запуске не показывать
                loadFlag = false;
                return;
            }
            else
                MessageBox.Show(String.Format("Вы выбрали планету {0}", planets1[index]));
        }
    }
}
                            Листинг
                        24.9.
                        Код файла Form1.cs   
- 
 Откомпилируйте
    приложение текущего уровня готовности и испытайте его работу Откомпилируйте
    приложение текущего уровня готовности и испытайте его работу
 
                             
