Поднял тему, а то ответа нету, может затерялась на просторах .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 >>
Здравствуйте, sniveller, Вы писали:
Может весь прикол в том что Size это
sctruct
а твой line наверное
class... << RSDN@Home 1.1 beta 1 silent>>
Здравствуйте, sniveller, Вы писали:
S>Поднял тему, а то ответа нету, может затерялась на просторах .NET
S>Оригинальная ветвь http://www.rsdn.ru/forum/Message.aspx?mid=370123&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 в ПропертиГрид меняется (типа толщина и цвет) а на форме результата не видно. Таки вопрос — может надо какой нибудь атрибут привязать? Или каким нибудь еще способом уведомить мой компонент о том, что его свойство частично изменилось?
атрибуты смотри... Есть там парочка: один заставляет все проперти перечитать, а второй перерисовку сделать...
Здравствуйте, 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>>
Использовал твой код для своего компонента (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);
}
...