Сложное свойство
От: sniveller  
Дата: 17.10.03 05:10
Оценка:
Поднял тему, а то ответа нету, может затерялась на просторах .NET

Оригинальная ветвь http://www.rsdn.ru/forum/Message.aspx?mid=370123&only=1
Автор: sniveller
Дата: 01.09.03


Предыстория:
Пишу компонент и в нем есть сложное свойство с подсвойствами. Orangy рассказал про ExpandableObjectConverter, спасибо ему за это

O>Здравствуйте, sniveller, Вы писали:


S>>Еще вопросик — а как сделать чтобы в свойствах мое сложное свойство распадалось на несколько простых (типа как Size на Width и Height)?

O>Отнаследоваться от ExpandableObjectConverter и при необходимости переопределить GetProperties

но возник такой вопрос:
Вот я создал компонент, у него есть это сложное свойство к которому привязан ExpandableObjectConverter. Все нормально видится в ПропертиГриде, свойства этого сложного свойства редактируются и т.д. Непонятка вот в чем: у меня на set этого свойства в компоненте стоит логика (проверка значения, перерисовка). Так вот этот set срабатывает только когда происходит загрузка компонента или когда свойство изменяется целиком. Если же я изменяю в дизайн тайме подсвойство сложного свойства то логика не срабатывает — то есть set не выполняется. То есть когда у Size меняешь Width в ПропертиГрид меняется не только строка у Size (ну там 100;200) а еще и форма автоматом изменяет размер, а у меня если в Line (к примеру) меняешь Color или Width то Line в ПропертиГрид меняется (типа толщина и цвет) а на форме результата не видно. Таки вопрос — может надо какой нибудь атрибут привязать? Или каким нибудь еще способом уведомить мой компонент о том, что его свойство частично изменилось?
... << RSDN@Home 1.1 beta 2 >>
Re: Сложное свойство
От: V.Petrovski Беларусь  
Дата: 17.10.03 07:33
Оценка:
Здравствуйте, sniveller, Вы писали:

Может весь прикол в том что Size это sctruct
а твой line наверное class
... << RSDN@Home 1.1 beta 1 silent>>
Re: Сложное свойство
От: AlexK Украина  
Дата: 17.10.03 08:00
Оценка:
Здравствуйте, sniveller, Вы писали:

S>Поднял тему, а то ответа нету, может затерялась на просторах .NET


S>Оригинальная ветвь http://www.rsdn.ru/forum/Message.aspx?mid=370123&amp;only=1
Автор: sniveller
Дата: 01.09.03


S>Предыстория:

S>Пишу компонент и в нем есть сложное свойство с подсвойствами. Orangy рассказал про ExpandableObjectConverter, спасибо ему за это

O>>Здравствуйте, sniveller, Вы писали:


S>>>Еще вопросик — а как сделать чтобы в свойствах мое сложное свойство распадалось на несколько простых (типа как Size на Width и Height)?

O>>Отнаследоваться от ExpandableObjectConverter и при необходимости переопределить GetProperties

S>но возник такой вопрос:

S>Вот я создал компонент, у него есть это сложное свойство к которому привязан ExpandableObjectConverter. Все нормально видится в ПропертиГриде, свойства этого сложного свойства редактируются и т.д. Непонятка вот в чем: у меня на set этого свойства в компоненте стоит логика (проверка значения, перерисовка). Так вот этот set срабатывает только когда происходит загрузка компонента или когда свойство изменяется целиком. Если же я изменяю в дизайн тайме подсвойство сложного свойства то логика не срабатывает — то есть set не выполняется. То есть когда у Size меняешь Width в ПропертиГрид меняется не только строка у Size (ну там 100;200) а еще и форма автоматом изменяет размер, а у меня если в Line (к примеру) меняешь Color или Width то Line в ПропертиГрид меняется (типа толщина и цвет) а на форме результата не видно. Таки вопрос — может надо какой нибудь атрибут привязать? Или каким нибудь еще способом уведомить мой компонент о том, что его свойство частично изменилось?

атрибуты смотри... Есть там парочка: один заставляет все проперти перечитать, а второй перерисовку сделать...
Re: Сложное свойство
От: V.Petrovski Беларусь  
Дата: 17.10.03 08:50
Оценка: 16 (4)
Здравствуйте, sniveller, Вы писали:

Вот все что надо сделать чтобы все работало. Кстати не важно struct или class

Сама сущность и её конвертор
    // можно поставить и class, т.к. при изменении его св-ва в PGrid будет создоваться заново экземпляр.
    // а вот в коде можно будет так testForm.Line.Width = 1 И это изменение не отловить в св-ве testForm.Line
    [TypeConverter(typeof(LineConverter))]
    public struct Line 
    {
        int width;
        Color color;
        public Line(int width, Color color)
        {
            this.width = width;
            this.color = color;
        }
        public int Width
        { 
            get
            {
                return width;
            }
            set
            {
                width = value;
            }
        }
        public Color Color
        { 
            get
            {
                return color;
            }
            set
            {
                color = value;
            }
        }
        public override string ToString()
        {
            return String.Format("{0} width {1}", color, width);
        }
    }

    public class LineConverter : TypeConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(InstanceDescriptor))
            {
                return true; 
            }
            return base.CanConvertTo (context, destinationType);
        }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if ((destinationType == typeof(InstanceDescriptor)) && (value is Line))
            {
                Line line = (Line)value;
                Type[] array = new Type[2];
                array[0] = typeof(int);
                array[1] = typeof(Color);
                ConstructorInfo info = typeof(Line).GetConstructor(array);
                if (info != null)
                {
                    object[] values = new object[2];
                    values[0] = line.Width;
                    values[1] = line.Color;
                    return new InstanceDescriptor(info, values); 
                }
             }
            return base.ConvertTo(context, culture, value, destinationType);
        }
        public override object CreateInstance(ITypeDescriptorContext context, System.Collections.IDictionary propertyValues)
        {
            return new Line((int)propertyValues["Width"],(Color)propertyValues["Color"]);
        }
        public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            PropertyDescriptorCollection collection;
            string[]    props = new string[]{"Color", "Width"};
            collection = TypeDescriptor.GetProperties(typeof(Line), attributes);
            return collection.Sort(array); 
        }
        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
    }
}


А вот его использование


        private Line line = new Line(1,Color.Black);
        /// <summary>
        /// Линия
        /// </summary>
        [Browsable(true)]
        [Description("Линия")]
        [TypeConverter(typeof(LineConverter))]
        public Line Line
        {
            get
            {
                return line;
            }
            set
            {
            // если Line - struct, то мы сюда попопед при людом изменнии мв-в Line
            // а вот если class, то только при такой записи testForm.Line = линия
                line = value;
            }
        }


Вот как это выглядит в PropertyGrid



А так выглядит в коде

private void InitializeComponent()
{
...
    this.testForm.Line = new Line(1, System.Drawing.Color.Silver);
...
}
... << RSDN@Home 1.1 beta 1 silent>>
Re[2]: Сложное свойство
От: maximoff  
Дата: 27.02.07 06:04
Оценка: +1
Использовал твой код для своего компонента (IPControl: свойство для отображения IP-адреса) и в следующем методе кажется опечатка:

Сама сущность и её конвертор

...
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            PropertyDescriptorCollection collection;
            string[]    props = new string[]{"Color", "Width"};
            collection = TypeDescriptor.GetProperties(typeof(Line), attributes);
            return collection.Sort(array); 
        }
...



Кажется array нужно заменить на props:

...
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            PropertyDescriptorCollection collection;
            string[]    props = new string[]{"Color", "Width"};
            collection = TypeDescriptor.GetProperties(typeof(Line), attributes);
            return collection.Sort(props); 
        }
...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.