自定義集合屬性
自定義控件中的屬性锥累,如果是集合的話成翩,例如List<T>,需要保證T類是可序列化的(注意叮雳,C#的控件都是繼承與Control的想暗,因此并不能序列化妇汗,因為序列化要求父類也是可序列化的),方法很簡單说莫,在T類上增加注解[Serializable]
[Serializable]
public class MultiStageItem
如果想要通過窗體的屬性設(shè)計器來設(shè)計集合屬性的話杨箭,為了使在設(shè)計器中的修改生效,必須在集合屬性上添加注解[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
DesignerSerializationVisibility(Design erSerializationVisibility.Visible)指定應(yīng)該允許序列化程序序列化屬性的值互婿;
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)指定序列化程序應(yīng)該序列化屬性的內(nèi)容,而不是屬性本身辽狈。此字段為只讀擒悬,Visible為其默認值。
只有指定了改特性后稻艰,點擊“集合編輯器”的確定按鈕后懂牧,VS.studio才能生成相應(yīng)的添加代碼(即對屬性進行序列化)。
還要添加編輯器[Editor()]注解
目前我寫的集合屬性的注解包括以下內(nèi)容:
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);
}
}
}
但是有個問題目前還沒有解決辦法尊勿,在修改控件之后再重新編譯僧凤,設(shè)計器會報錯:
“不能將MultiStageItem[]轉(zhuǎn)換為MultiStageItem[]類型”,目前我找不到解決辦法元扔。遇到這個問題躯保,重啟VS之后就會恢復(fù)。然后不定時又會出問題澎语。
更新與2017年11月23日
找到了一個解決辦法途事,目前沒有出問題。
關(guān)鍵是要對集合屬性中的類進行序列化擅羞。由于自定義的類中包含Color尸变、Font等沒有序列化方法的類,所以需要自定義序列化减俏。
1. 首先實現(xiàn)ISerializable接口
public class MultiStageItem : ISerializable{
}
2. 序列化Color
/// <summary>
/// 序列化顏色屬性召烂,將顏色轉(zhuǎn)成字符串
/// </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>
/// 反序列化顏色屬性,從字符串轉(zhuǎn)換成顏色
/// </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>
/// 將字體轉(zhuǎn)換成屬性類
/// </summary>
/// <param name="f">字體</param>
public FontStruct(Font f)
{
fontFamily = f.FontFamily.Name;
unit = f.Unit;
size = f.Size;
style = f.Style;
}
/// <summary>
/// 將屬性類轉(zhuǎn)成字體
/// </summary>
/// <returns>字體</returns>
public Font toFont()
{
return new Font(fontFamily, size, style, unit);
}
}
4. 增加整體對象的序列化和反序列化函數(shù)
通過構(gòu)造函數(shù)實現(xiàn)反序列化
/// <summary>
/// 普通構(gòu)造函數(shù)
/// </summary>
public MultiStageItem() { }
/// <summary>
/// 反序列化的構(gòu)造函數(shù)
/// </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);
}