Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 24:

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

Развертывание свойств вложенного объекта компонента

Чтобы обеспечить корректное развертывание и редактирование свойств вложенного объекта, необходимо прикрепить к его описанию атрибут System.ComponentModel. TypeConverter, ссылающийся на библиотечный тип System.ComponentModel. ExpandableObjectConverter. Атрибут является дополнительной информацией для компилятора сделать сложное свойство компонента развертываемым. Прикрепленный атрибут является классом, по которому оболочка сама создаст объект, обеспечивающий развертывание и редактирование свойств вложенного объекта.

  • Перед описанием класса SomeObject в файле FirstComponent.cs вставьте соответствующую инструкцию прикрепления атрибута, чтобы заголовок класса SomeObject стал таким
namespace MyCompany.MyComponents
{
    // Прикрепляем простой атрибут для возможности развертывания 
    // и редактирования свойств объекта в панели Properties оболочки
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class SomeObject : Object
    {
        int prop1;
        string prop2;
    
        // Свойства
        public int Prop1
        {
            get { return prop1; }
            set { prop1 = value; }
        }
    
        public string Prop2
        {
            get { return prop2; }
            set { prop2 = value; }
        }
    
        // Инициализация полей через конструктор
        public SomeObject()
        {
            prop1 = 2008;
            prop2 = "Привет";
        }
    }
}
Листинг 24.3. Прикрепление простого атрибута развертывания и редактирования
  • В панели Solution Explorer вызовите контекстное меню для узла проекта MyComponents и выполните команду Build, чтобы откомпилировать новую редакцию компонента
  • Перейдите на форму Form1, опять выделите экземпляр нашего компонента и исследуйте его свойство SomeObj

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

Чтобы исправить это, нужно переопределить методы класса ExpandableObjectConverter, которые он унаследовал от базового класса TypeConverter:

  • CanConvertFrom() - проверяет, можно ли выполнить преобразование типов
  • ConvertFrom() - преобразует составную строку в значения свойств
  • ConvertTo() - преобразует значения свойств в составную строку

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

  • Через контекстное меню панели Solution Explorer добавьте к проекту MyComponents новый файл с именем Converter.cs


  • Наполните файл Converter.cs следующим кодом
using System;
using System.ComponentModel;
    
namespace MyCompany.MyComponents
{
    // Контролирующий класс, предоставляющий возможность 
    // развертывания и редактирования свойств вложенных объектов
    public class SomeObjectConverter : ExpandableObjectConverter
    {
        // Проверяем возможность преобразования типов
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            // Проверяем тип составной строки 
            if (sourceType == typeof(System.String))
                return true;
            else
                return base.CanConvertFrom(context, sourceType);
        }
    
        // Преобразуем составную строку в значения свойств
        public override object ConvertFrom(ITypeDescriptorContext context, 
            System.Globalization.CultureInfo culture, object value)
        {
            string sourceStr = value as System.String;
            // Если очистить строку, восстанавливаем исходный объект
            if (sourceStr == "")
            {
                return new SomeObject();
            }
            else
            {
                // Расщепляем строку свойств
                char[] separator ={ ';' };
                string[] PropStrings = sourceStr.Split(separator);
                // Проверяем число элементов строки и в случае несовпадения
                // генерируем исключение, перехватываемое оболочкой 
                if (PropStrings.Length != 2)
                    throw new ArgumentException(
                        "Требуется формат: два значения с разделителем ';'");
                // Создаем новый объект и присваиваем свойствам новые значения
                SomeObject obj = new SomeObject();
                obj.Prop1 = Convert.ToInt32(PropStrings[0].Trim());
                obj.Prop2 = PropStrings[1].Trim();
                return obj;
            }
        }
    
        // Преобразуем значения свойств в составную строку
        public override object ConvertTo(ITypeDescriptorContext context, 
            System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            SomeObject obj = (SomeObject)value;
            return obj.Prop1.ToString() + "; " + obj.Prop2;
        }
    }
}
Листинг 24.4. Код файла Converter.cs
  • Замените в объявлении класса SomeObject введенный ранее простой атрибут, ссылающийся на базовый класс ExpandableObjectConverter, новым атрибутом, ссылающимся на производный класс SomeObjectConverter
namespace MyCompany.MyComponents
{
    // Прикрепляем простой атрибут для возможности развертывания 
    // и редактирования свойств объекта в панели Properties оболочки
    //[TypeConverter(typeof(ExpandableObjectConverter))]
  
    // Прикрепляем атрибут с контролирующим классом для возможности
    // редактирования свойств объекта в панели Properties оболочки
    [TypeConverter(typeof(SomeObjectConverter))]
    public class SomeObject : Object
    {
        int prop1;
        string prop2;
    
        // Свойства
        public int Prop1
        {
            get { return prop1; }
            set { prop1 = value; }
        }
    
        public string Prop2
        {
            get { return prop2; }
            set { prop2 = value; }
        }
    
        // Инициализация полей через конструктор
        public SomeObject()
        {
            prop1 = 2008;
            prop2 = "Привет";
        }
    }
}
Листинг 24.5. Прикрепление нового атрибута развертывания и редактирования

Вспомогательный класс SomeObjectConverter, будучи прикрепленным в качестве атрибута к классу SomeObject, преобразует содержимое свойств Prop1 и Prop2 в строку и обратно. Это действие выполняется классом с помощью его перегруженных методов, автоматически вызываемых оболочкой в режиме проектирования через панель Properties.

  • В панели Solution Explorer вызовите контекстное меню для узла проекта MyComponents и выполните команду Build, чтобы откомпилировать новую редакцию компонента
  • Перейдите на форму Form1, опять выделите экземпляр нашего компонента и исследуйте его свойство SomeObj

Замечание: Если после произведенных дополнений к коду компонента поведение свойства SomeObj в панели Properties не изменилось, то перезагрузите саму оболочку Visual Studio 2005.

Теперь сложное свойство SomeObj вложенного объекта экземпляра компонента помимо прежней функциональности разварачиваться и редактироваться в панели Properties стало отображаться и редактироваться в составной строке самого свойства.


Александр Очеретяный
Александр Очеретяный
Украина, Киев
Анастасия Балыбердина
Анастасия Балыбердина
Украина, Киев, НТУУ КПИ