Re[3]: .Net – классы, компоненты и контролы
От: Аноним  
Дата: 14.05.09 06:44
Оценка:
Господа, снова нужна помощь. Сделал так, как понял, но не все работает.

Как я писал выше, имеется юзер контрол.
В нем есть свойство:
public Type BindForm
        {
            get
            {
                return bFormValue;
            }
            set
            {
                try
                {
                    if (value.BaseType != typeof(Form) && value != typeof(Form))
                    {
                        throw new InvalidCastException("Должна быть форма.");
                    }
                    bFormValue = value;
                }
                catch (InvalidCastException ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }


Хочу редактировать это свойство особым образом. Смысл в том, чтобы разработчик выбирал, какую форму он хочет открыть (при нажатии кнопки на контроле).

Для этого "подменяю" реальное свойство виртуальным типа string:

        protected override void PreFilterProperties(
          System.Collections.IDictionary properties)
        {
            base.PreFilterProperties(properties);
            //const string sPropName = "Тестовое свойство";
            const string sPropName = "BindForm";
            // Добавляем виртуальное свойство, доступное только во время разработки.
            properties[sPropName] = new BindFormPropertyDescriptor(this,
              TypeDescriptor.CreateProperty(
                Component.GetType(),
                sPropName,
                typeof(String),
                new Attribute[] 
                    {
                      // Задаем категорию, в которой будет отображаться новое свойство.
                      CategoryAttribute.Data
                      // Говорим VS.NET, что при изменении этого свойства нужно 
                      // перечитать значение остальных свойств.
                      , RefreshPropertiesAttribute.All
                      //Назначим свой редактор для свойства
                      , new EditorAttribute(typeof(BindFormEditor), typeof(System.Drawing.Design.UITypeEditor))
                    }));
        }


Далее, реализую Editor для установки значения для этого виртуального свойства. Код приводить не будет, он большой.

Короче, до этого момента все работает замечательно.

Теперь хочу сделанные изменения сеарилизовать в код, чтобы он (она — Студия) записывал значение реального поля в Designer.cs

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

    public class FromTypeConverter : TypeConverter
    {
        // Overrides the CanConvertFrom method of TypeConverter.
        // The ITypeDescriptorContext interface provides the context for the
        // conversion. Typically, this interface is used at design time to 
        // provide information about the design-time container.
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            MessageBox.Show("FromTypeConverter.CanConvertFrom");
            if (sourceType == typeof(string))
            {
                return true;
            }
            return base.CanConvertFrom(context, sourceType);
        }
        // Overrides the ConvertFrom method of TypeConverter.
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            try
            {
                MessageBox.Show("FromTypeConverter.ConvertFrom");
                if (value is string)
                {
                    //string[] v = ((string)value).Split(new char[] { ',' });
                    //return new Point(int.Parse(v[0]), int.Parse(v[1]));
                    if (value.ToString() == "")
                    {
                        return null;
                    }
                    else
                    {
                        return Type.GetType(value.ToString());
                    }
                }
                return base.ConvertFrom(context, culture, value);
            }
            catch (System.IO.FileNotFoundException ex)
            {
                MessageBox.Show(ex.Message);
                return base.ConvertFrom(context, culture, value);
            }
        }
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            MessageBox.Show("FromTypeConverter.CanConvertTo");
            if (destinationType == typeof(InstanceDescriptor))
                return true;
            // Всегда вызываем базовый класс если не можем 
            // совершить преобразование сами.
            return base.CanConvertTo(context, destinationType);
        }
        // Overrides the ConvertTo method of TypeConverter.
        public override object ConvertTo(ITypeDescriptorContext context,
           CultureInfo culture, object value, Type destinationType)
        {
            MessageBox.Show("FromTypeConverter.ConvertTo");
            if (destinationType == typeof(string))
            {
                //return ((Point)value).X + "," + ((Point)value).Y;
                return ((Type)value).AssemblyQualifiedName;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }


Ну и теперь включаю непосредственно сериализацию (или думаю, что включаю):

    [TypeConverter(typeof(FromTypeConverter))] //Вот тут
    [Designer(typeof(BindFormComponentDesigner)), DesignerCategory("Default")] //А это дизайнер для виртуального создания свойства
    public partial class UserControl1 : UserControl


Так вот ничего не происходит. Полученное значение не записывает в исходный код. В самом поле я его вижу, могу даже поменять и т.д. А как его в исходник загнать?

Что я делаю не так?

Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.