Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 889 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 24:

Пользовательские компоненты

Упражнение 2. Создание невизуального компонента Planets

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

  • В панели 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, чтобы перекомпилировать проект с компонентами
  • Убедитесь, что в панели Toolbox появился новый компонент Planets, который теперь можно перетаскивать на форму также, как и обычный библиотечный компонент

Испытание созданных компонентов

  • В проекте ComponentTest настройте пользовательский интерфейс, как показано на рисунке и в таблице (в скобках приведены имена экземпляров компонентов)


Таблица свойств элементов интерфейса
Элемент Свойство Значение
Form1 MaximizeBox false
Size 324; 224
  Text Испытание компонентов
listPlanets FormattingEnabled true
ItemHeight 16
  Location 12; 12
  Size 109; 164
indexPlanet Location 160; 153
  Size 26; 22
textBox1 BorderStyle None
Font Microsoft Sans Serif; 12pt; style=Bold
  Location 138; 21
  Multiline true
  ReadOnly true
  Size 166; 107
  Text Введите индекс планеты и щелкните на красном
  TextAlign Center
firstComponent1 Location 201; 153
  Size 75; 23
  • В панели Properties перейдите на вкладку Events и создайте обработчики для элементов согласно таблицы
Таблица событий элементов интерфейса
Элемент Событие Имя обработчика
listPlanets SelectedIndexChanged listPlanets_SelectedValueChanged
indexPlanet KeyPress indexPlanet_KeyPress
firstComponent1 Click firstComponent1_Click
  • Заполните файл 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
  • Откомпилируйте приложение текущего уровня готовности и испытайте его работу