自定义集合属性
自定义控件中的属性,如果是集合的话,例如List<T>,需要保证T类是可序列化的(注意,C#的控件都是继承与Control的,因此并不能序列化,因为序列化要求父类也是可序列化的),方法很简单,在T类上增加注解[Serializable]
[Serializable]
public class MultiStageItem
如果想要通过窗体的属性设计器来设计集合属性的话,为了使在设计器中的修改生效,必须在集合属性上添加注解[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
DesignerSerializationVisibility(Design erSerializationVisibility.Visible)指定应该允许序列化程序序列化属性的值;
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)指定序列化程序应该序列化属性的内容,而不是属性本身。此字段为只读,Visible为其默认值。
只有指定了改特性后,点击“集合编辑器”的确定按钮后,VS.studio才能生成相应的添加代码(即对属性进行序列化)。
还要添加编辑器[Editor()]注解
目前我写的集合属性的注解包括以下内容:
private List<MultiStageItem> subAttriList = new List<MultiStageItem>();
[Description("菜单项属性列表"), Category("自定义属性")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MergableProperty(false)]
[TypeConverter(typeof(System.ComponentModel.CollectionConverter))]
[Editor(typeof(System.ComponentModel.Design.CollectionEditor), typeof(System.Drawing.Design.UITypeEditor))]
public List<MultiStageItem> SubAttriList
{
get { return subAttriList; }
set
{
List<MultiStageItem> list = value;
subAttriList.Clear();
foreach (MultiStageItem i in list)
{
subAttriList.Add(i);
}
}
}
但是有个问题目前还没有解决办法,在修改控件之后再重新编译,设计器会报错:
“不能将MultiStageItem[]转换为MultiStageItem[]类型”,目前我找不到解决办法。遇到这个问题,重启VS之后就会恢复。然后不定时又会出问题。
更新与2017年11月23日
找到了一个解决办法,目前没有出问题。
关键是要对集合属性中的类进行序列化。由于自定义的类中包含Color、Font等没有序列化方法的类,所以需要自定义序列化。
1. 首先实现ISerializable接口
public class MultiStageItem : ISerializable{
}
2. 序列化Color
/// <summary>
/// 序列化颜色属性,将颜色转成字符串
/// </summary>
/// <param name="clr">颜色</param>
/// <returns>字符串</returns>
private string serializeColor(Color clr)
{
return string.Format("{0}:{1}:{2}:{3}", clr.A, clr.R, clr.G, clr.B);
}
/// <summary>
/// 反序列化颜色属性,从字符串转换成颜色
/// </summary>
/// <param name="color">字符串</param>
/// <returns>颜色</returns>
private Color deserializeColor(string color)
{
string[] pieces = color.Split(':');
byte a = byte.Parse(pieces[0]),
r = byte.Parse(pieces[1]),
g = byte.Parse(pieces[2]),
b = byte.Parse(pieces[3]);
return Color.FromArgb(a, r, g, b);
}
3. 序列化Font
/// <summary>
/// 用于序列化的字体属性类
/// </summary>
[Serializable]
private struct FontStruct
{
public string fontFamily;
public GraphicsUnit unit;
public float size;
public FontStyle style;
/// <summary>
/// 将字体转换成属性类
/// </summary>
/// <param name="f">字体</param>
public FontStruct(Font f)
{
fontFamily = f.FontFamily.Name;
unit = f.Unit;
size = f.Size;
style = f.Style;
}
/// <summary>
/// 将属性类转成字体
/// </summary>
/// <returns>字体</returns>
public Font toFont()
{
return new Font(fontFamily, size, style, unit);
}
}
4. 增加整体对象的序列化和反序列化函数
通过构造函数实现反序列化
/// <summary>
/// 普通构造函数
/// </summary>
public MultiStageItem() { }
/// <summary>
/// 反序列化的构造函数
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public MultiStageItem(SerializationInfo info, StreamingContext context)
{
Width = info.GetInt32("Width");
Height = info.GetInt32("Height");
backColor = deserializeColor(info.GetString("backColor"));
focusColor = deserializeColor(info.GetString("focusColor"));
font = ((FontStruct)info.GetValue("font", typeof(FontStruct))).toFont();
foreColor = deserializeColor(info.GetString("foreColor"));
leftMargin = info.GetInt32("leftMargin");
titleText = info.GetString("titleText");
subList = (List<MultiStageItem>)info.GetValue("subList", typeof(List<MultiStageItem>));
}
/// <summary>
/// 将对象序列化
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
//throw new NotImplementedException();
info.AddValue("Width", Width);
info.AddValue("Height", Height);
info.AddValue("backColor", serializeColor(backColor));
info.AddValue("focusColor", serializeColor(focusColor));
info.AddValue("font", new FontStruct(font));
info.AddValue("foreColor", serializeColor(foreColor));
info.AddValue("leftMargin", leftMargin);
info.AddValue("titleText", titleText);
info.AddValue("subList", subList);
}