Litvek: лучшие книги недели
Топ книга - Книга Балтиморов [Жоэль Диккер] - читаем полностью в LitvekТоп книга - Атомные привычки [Джеймс Клир] - читаем полностью в LitvekТоп книга - Обреченные обжечься [Anne Dar] - читаем полностью в LitvekТоп книга - Законный брак [Делия Росси] - читаем полностью в LitvekТоп книга - Легенда о Пиросмани [Валериан Маркаров] - читаем полностью в LitvekТоп книга - Бывшие, или У любви другие планы (СИ) [Татьяна Серганова] - читаем полностью в LitvekТоп книга - Сестра ветра [Люсинда Райли] - читаем полностью в LitvekТоп книга - Академия [Марина Суржевская] - читаем полностью в Litvek
Litvek - онлайн библиотека >> Морган Скиннер и др. >> C, C++, C# и др. >> C# для профессионалов. Том II >> страница 201
новый проект Visual C# — Windows Application и назовем его ControlLoader. В самом начале мы не будем размещать в новой форме никаких элементов управления, но можем изменить свойство Text на что-нибудь типа "Control Container".

Итак, добавим следующие члены в форму:

public class Form1 : System.Windows.Forms.Form {

 // члены ...

 private ArrayList _buttons = new ArrayList();

 private int _nextY = ButtonSpacing;

 private Control _containedControl;

 // константы ...

 const int ButtonHeight = 25;

 const int ButtonSpacint = 5;

 const int ButtonWidth = 200;

Мы имеем список кнопок, которые добавляются в ArrayList с именем _buttons. При добавлении каждой кнопки к форме необходимо разместить ее в правильной у-координате, т.е. _nextY. Рассмотрим только один элемент управления в конкретный момент, который будет содержаться в _containedControl. Наконец, мы используем метрику, которая описывает компоновку кнопок, и она задается тремя константами внизу.

Сами кнопки будут создаваться из нового класса, производного от System.Windows.Forms.Button. Этот новый класс называется TypeButton и имеет дополнительное свойство ControlType, которое содержит объект System.Type. Этот объект Type представляет элемент управления в загружаемой сборке. Создадим новый класс с именем TypeButton и добавим ссылку на пространство имен System.Windows.Forms.

using System;

using System.Windows.Forms;

Затем добавим код:

public class TypeButton System.Windows.Forms.Button {

 public Type _controlType;


 public TypeButton() {

 }


 // ControlType — получить или задать свойство ...

 public Type ControlType {

  get {

   return _controlType;

  }

  set {

   _controlType = value;

   this.Text = _controlType.FullName;

  }

 }

}

Как можно видеть, задавая свойство ControlType, мы изменяем текст кнопки, чтобы он стал полным названием типа.

Метод, который нужен для создания TypeButton, создает экземпляр элемента управления. Добавим этот метод, использующий System.Activator для создания экземпляра класса и преобразующий его в System.Windows.Forms.Control:

// CreateInstance — создание экземпляра типа данных ... 

public Control CreateInstance() {

 // возвращает экземпляр нового элемента управления ...

 return (Control)Activator.CreateInstance(ControlType);

}

Добавление кнопок
Для первого проверочного запуска добавим TypeButton, который представляет экземпляр элемента управления System.Windows.Forms.DataGrid. Это позволит протестировать логику того, что делается, не вдаваясь в дополнительные трудности, связанные с загрузкой сборки и просмотром типов данных.

Метод Form1.AddType будет получать объект System.Type и добавлять новый объект TypeButton в форму. Во-первых, необходимо создать экземпляр TypeButton и задать его свойство ControlType новым типом:

// AddType - добавить кнопку типа в компоновку ...

public void AddType(Type ControlType) {

 // первое: создать новую кнопку типа ...

 TypeButton button = new TypeButton();

 button.ControlType = ControlType;

Во-вторых, нужно добавить TypeButton в ArrayList, который содержит список кнопок:

 // второе: добавить эту кнопку в массив

 _buttons.Add(button);

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

 // теперь разместим кнопку

 button.Left = ButtonSpacing;

 button.Width = ButtonWidth;

 button.Top = _nextY;

 button.Height = ButtonHeight;

 // настроить следующее значение у ...

 _nextY += (ButtonHeight + ButtonSpacing);

 // вывести кнопку ...

 this.Controls.Add(button);

Наконец, необходимо присоединить событие click (нажатие) кнопки таким образом, чтобы мы могли иметь экземпляр элемента управления, который он представляет:

 // затем присоединяем обработчик события ...

 button.Click += new EventHandler(this.ButtonClick);

}

Пока еще мы не создали ButtonClick, — сделаем это сейчас:

// ButtonClick — вызывается всякий раз при нажатии кнопки ...

protected void ButtonClick(object sender, System.EventArgs e) {

 // преобразовать sender в кнопку типа ...

 TypeButton button = (TypeButton)sender;

Нашей первой задачей является преобразование sender в TypeButton. Это позволит использовать CreateInstance для создания элемента управления. Если мы уже имеем элемент управления, необходимо сначала удалить его из списка элементов управления формы:

// если уже имеется содержащийся элемент управления, удалим его ...

 if (_containedControl != null)

  Controls.Remove(_containedControl);

Создаем элемент управления:

 // создать экземпляр нового элемента управления...

 _containedControl = button.CreateInstance();

Наконец, мы можем поместить элемент управления в форму.

 // поместить элемент управления на форме ...

 _containedControl.Left = ButtonWidth + (3 * ButtonSpacing);

 _containedControl.Top = ButtonSpacing;

 _containedControl.Width = this.Width - _containedControl.Left - (4 * ButtonSpacing);

 _containedControl.Height = this.Height - (8 * ButtonSpacing);

 this.Controls.Add(_containedControl);

}

Тестирование полученного кода
Прежде чем можно будет увидеть окончательный вариант сделанного, необходимо добавить кнопку в форму. Используем элемент управления System Windows.Forms.DataGrid. Добавим следующий код в Form1:

private void Form1_Load(object sender, System.EventArgs e) {

 // при загрузке добавить тип кнопки ...

 DataGrid grid = new DataGrid();

 AddType(grid.GetType());

}

Теперь закончим проект. Нажав на кнопку System.Windows.Forms.DataGrid, увидим:

C# для профессионалов. Том II. Иллюстрация № 194

Загрузка сборки

Завершая этот пример, покажем, как можно загрузить сборку во время выполнения, просмотреть сборку в поисках типов данных, которые являются произвольными из System.Windows.Forms.Control, и добавить кнопки для каждого найденного типа данных.

Чтобы загрузить сборку нам понадобится URL. Добавим следующий код в Form1_Load:

private void Form1_Load(object sender, System.EventArgs e) {

 // при загрузке добавить тип кнопки ...

 DataGrid grid = new DataGrid();

 AddType(grid.GetType());

 // найти имя нашей сборки

 String filename = this.GetType().Module.Assembly.CodeBase;

Эта строка является обходной техникой для получения сборки, реализующей класс объекта, из которого вызывается код. В данном случае ее получают из URL сборки, содержащей Form1.

Нам нужно при загрузке сборки использовать try…catch, так как существуют процессы, которые могут пойти в этой процедуре неправильно. Мы используем общий метод на Assembly:

 // проверить и загрузить сборку ...

 try {

  // используем LoadFrom ...

  Assembly controlAssembly = Assembly.LoadFrom(filename);

После получения сборки проверим в ней типы данных:

  // теперь получим список типов данных ...

  foreach(Type testType in controlAssembly.GetTypes()) {

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

   // попробуем создать экземпляр элемента управления

   // и преобразовать его в элемент управления ...

   try {

    Control testControl = (Control)Activator.CreateInstance(testType);

Полезный совет. System.Windows.Forms.Form является производным от Control, так как он использует