在定义的属性名称上面一行加上 例: [CategoryAttribute("lz所说加号所标示的内容名称")] public virtual ItemControlType 元素类型 { get { return this.ItemType; } }CategoryAttribute:定义属性的分组
CategoryAttribute好像不顶用LZ要的好像是类似Font的模式
要使用类型转换器,且你自定义的类型转换器要继承自ExpandableObjectConverter ,这就是实现可折叠的功能 给你看个例子(非完整的)//标出你的类型转换器 [TypeConverter(typeof(MapRectangleConverter))] public class MapRectangle: { private MapPoint _leftTop; private MapPoint _bottomRight; public MapRectangle() : this(new MapPoint(), new MapPoint()) { } public MapRectangle(MapPoint leftTop, MapPoint bottomRight) { this._leftTop = leftTop; this._bottomRight = bottomRight; } [DefaultValue(typeof(MapPoint),"")] [NotifyParentProperty(true)] public MapPoint LeftTop { get { return _leftTop; } set { _leftTop = value; } } [DefaultValue(typeof(MapPoint), "")] [NotifyParentProperty(true)] public MapPoint BottomRight { get { return _bottomRight; } set { _bottomRight = value; } } public MapRectangle(int x1, int y1, int x2, int y2) : this(new MapPoint(x1, y1), new MapPoint(x2, y2)) { } public override bool IsEmpty { get { return (_bottomRight.IsEmpty && _leftTop.IsEmpty); } } }//自定义的类型转换器继承自ExpandableObjectConverter public class MapRectangleConverter:MapShapeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) return true; return base.CanConvertFrom(context, sourceType); } public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) return true; return base.CanConvertTo(context, destinationType); } public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value == null) return new MapRectangle(); if (value is string) { string s = (string)value; if (s.Length == 0) return new MapRectangle(); string[] parts = s.Split(culture.TextInfo.ListSeparator[0]); if (parts.Length != 4) throw new ArgumentException("Invalid MapRectangle", "value"); TypeConverter intConveter=TypeDescriptor.GetConverter(typeof(Int32)); return new MapRectangle((int)intConveter.ConvertFromString(context, culture, parts[0]), (int)intConveter.ConvertFromString(context, culture, parts[1]), (int)intConveter.ConvertFromString(context, culture, parts[2]), (int)intConveter.ConvertFromString(context, culture, parts[3])); } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (value != null) { if (!(value is MapRectangle) ) throw new ArgumentException("Invalid MapRectangle", "value"); } if(destinationType==typeof(string)) { if (value == null) return string.Empty; MapRectangle rect = (MapRectangle)value; if (rect.IsEmpty) { return String.Empty; } TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(Int32)); return String.Join(culture.TextInfo.ListSeparator, new string[] { intConverter.ConvertToString(context, culture, rect.LeftTop.X), intConverter.ConvertToString(context, culture, rect.LeftTop.Y), intConverter.ConvertToString(context, culture, rect.BottomRight.X), intConverter.ConvertToString(context, culture, rect.BottomRight.Y) }); } return base.ConvertTo(context, culture, value, destinationType); } }//且有复杂属性的控件 public class MapDemo { private MapRectangle _rectangle; //此属性可以折叠展开 [Category("Shape")] [DefaultValue(typeof(MapRectangle), "")] [Description("the location of the rectangular hot spot")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [NotifyParentProperty(true)] public MapRectangle Rectangle { get { if (_rectangle == null) _rectangle = new MapRectangle(); return _rectangle; } } }
修正一下,上面是继承过一次的,需要一个较完整的例子,可以发给你 //自定义的类型转换器继承自ExpandableObjectConverter public class MapRectangleConverter:ExpandableObjectConverter //还少一个类的代码 [TypeConverter(typeof(MapPointConverter))] public class MapPoint { private int _x; private int _y; public MapPoint() : this(0, 0) { } public MapPoint(int x, int y) { this._x = x; this._y = y; } public bool IsEmpty { get { return (_x == 0 && _y == 0); } } [NotifyParentProperty(true)] public int X { get { return _x; } set { _x = value; } } public int Y { get { return _y; } set { _y = value; } } public override bool Equals(object obj) { MapPoint other = obj as MapPoint; if (other != null) return (X == other.X) && (Y == other.Y); return false; } public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); } public override string ToString() { return ToString(CultureInfo.CurrentCulture); } public virtual string ToString(CultureInfo culture) { return TypeDescriptor.GetConverter(typeof(MapPoint)).ConvertToString(null, culture, this); } }这样,MapDemo的属性MapRectangle就可以展开,下面有x,y坐标
如果没有特殊要求,直接用ExpandableObjectConverter就可以了[TypeConverter(typeof(ExpandableObjectConverter ))] public class My { public string Name {get; set;} public Point Location {get; set;} public Color Color {get;set} } 如果有特殊要求,像动态属性,显示顺序,自定义错误信息等,则可参考 ICustomTypeDescriptor接口,或MSDN杂志文章:ICustomTypeDescriptor, Part 1/Part 2
多谢前两天忙没看,sorry
[System.ComponentModel.TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))] public class SizeInfo { }添加了之后,就可以看到所有的属性了
例:
[CategoryAttribute("lz所说加号所标示的内容名称")]
public virtual ItemControlType 元素类型
{
get
{
return this.ItemType;
}
}CategoryAttribute:定义属性的分组
给你看个例子(非完整的)//标出你的类型转换器
[TypeConverter(typeof(MapRectangleConverter))]
public class MapRectangle:
{
private MapPoint _leftTop;
private MapPoint _bottomRight; public MapRectangle() : this(new MapPoint(), new MapPoint()) { } public MapRectangle(MapPoint leftTop, MapPoint bottomRight)
{
this._leftTop = leftTop;
this._bottomRight = bottomRight;
} [DefaultValue(typeof(MapPoint),"")]
[NotifyParentProperty(true)]
public MapPoint LeftTop
{
get { return _leftTop; }
set { _leftTop = value; }
} [DefaultValue(typeof(MapPoint), "")]
[NotifyParentProperty(true)]
public MapPoint BottomRight
{
get { return _bottomRight; }
set { _bottomRight = value; }
} public MapRectangle(int x1, int y1, int x2, int y2) : this(new MapPoint(x1, y1), new MapPoint(x2, y2)) { } public override bool IsEmpty
{
get { return (_bottomRight.IsEmpty && _leftTop.IsEmpty); }
}
}//自定义的类型转换器继承自ExpandableObjectConverter
public class MapRectangleConverter:MapShapeConverter
{
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
} public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
return base.CanConvertTo(context, destinationType);
} public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value == null)
return new MapRectangle(); if (value is string)
{
string s = (string)value; if (s.Length == 0)
return new MapRectangle(); string[] parts = s.Split(culture.TextInfo.ListSeparator[0]);
if (parts.Length != 4)
throw new ArgumentException("Invalid MapRectangle", "value"); TypeConverter intConveter=TypeDescriptor.GetConverter(typeof(Int32)); return new MapRectangle((int)intConveter.ConvertFromString(context, culture, parts[0]),
(int)intConveter.ConvertFromString(context, culture, parts[1]),
(int)intConveter.ConvertFromString(context, culture, parts[2]),
(int)intConveter.ConvertFromString(context, culture, parts[3]));
}
return base.ConvertFrom(context, culture, value);
} public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value != null)
{
if (!(value is MapRectangle) )
throw new ArgumentException("Invalid MapRectangle", "value");
} if(destinationType==typeof(string))
{
if (value == null)
return string.Empty; MapRectangle rect = (MapRectangle)value;
if (rect.IsEmpty)
{
return String.Empty;
} TypeConverter intConverter = TypeDescriptor.GetConverter(typeof(Int32));
return String.Join(culture.TextInfo.ListSeparator,
new string[] {
intConverter.ConvertToString(context, culture, rect.LeftTop.X),
intConverter.ConvertToString(context, culture, rect.LeftTop.Y),
intConverter.ConvertToString(context, culture, rect.BottomRight.X),
intConverter.ConvertToString(context, culture, rect.BottomRight.Y)
});
} return base.ConvertTo(context, culture, value, destinationType);
}
}//且有复杂属性的控件
public class MapDemo
{
private MapRectangle _rectangle;
//此属性可以折叠展开
[Category("Shape")]
[DefaultValue(typeof(MapRectangle), "")]
[Description("the location of the rectangular hot spot")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[NotifyParentProperty(true)]
public MapRectangle Rectangle
{
get
{
if (_rectangle == null)
_rectangle = new MapRectangle(); return _rectangle;
}
}
}
修正一下,上面是继承过一次的,需要一个较完整的例子,可以发给你
//自定义的类型转换器继承自ExpandableObjectConverter
public class MapRectangleConverter:ExpandableObjectConverter //还少一个类的代码
[TypeConverter(typeof(MapPointConverter))]
public class MapPoint
{
private int _x;
private int _y; public MapPoint() : this(0, 0) { } public MapPoint(int x, int y)
{
this._x = x;
this._y = y;
} public bool IsEmpty
{
get
{
return (_x == 0 && _y == 0);
}
} [NotifyParentProperty(true)]
public int X
{
get { return _x; }
set { _x = value; }
} public int Y
{
get { return _y; }
set { _y = value; }
} public override bool Equals(object obj)
{
MapPoint other = obj as MapPoint; if (other != null)
return (X == other.X) && (Y == other.Y); return false;
} public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
} public override string ToString()
{
return ToString(CultureInfo.CurrentCulture);
} public virtual string ToString(CultureInfo culture)
{
return TypeDescriptor.GetConverter(typeof(MapPoint)).ConvertToString(null, culture, this);
}
}这样,MapDemo的属性MapRectangle就可以展开,下面有x,y坐标
public class My
{
public string Name {get; set;}
public Point Location {get; set;}
public Color Color {get;set}
}
如果有特殊要求,像动态属性,显示顺序,自定义错误信息等,则可参考
ICustomTypeDescriptor接口,或MSDN杂志文章:ICustomTypeDescriptor, Part 1/Part 2
public class SizeInfo
{
}添加了之后,就可以看到所有的属性了