美文网首页
c# 自定义控件的集合属性

c# 自定义控件的集合属性

作者: tiang | 来源:发表于2017-11-23 17:04 被阅读367次

自定义集合属性

自定义控件中的属性,如果是集合的话,例如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);
        }

相关文章

网友评论

      本文标题:c# 自定义控件的集合属性

      本文链接:https://www.haomeiwen.com/subject/yhrjvxtx.html