Visual Studio WinForms编辑器无法保存自定义集合修改问题
自定义List集合属性在Collection Editor中修改无法保存的解决办法
问题场景
- 自定义UserControl的集合属性使用继承自
List<T>的自定义类,通过Collection Editor编辑后,设计器能实时显示更新后的样式,但修改无法持久化:- Designer文件不会生成反序列化集合的代码(比如
notifierListLabel1.Ints = (DataClasses.NotifierList<int>)resources.GetObject("notifierListLabel1.Ints")这类代码) - 构建运行后控件恢复默认状态,设计器也会在几秒后自动还原
- Designer文件不会生成反序列化集合的代码(比如
- 已尝试给自定义集合类添加
[Serializable]特性、给属性添加[Editor(typeof(CollectionEditor), typeof(UITypeEditor))]特性,均无效;但使用原生List<T>作为属性类型时,修改能正常保存
解决方案
给自定义集合属性添加[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]特性,示例代码如下:
public class YourCustomUserControl : UserControl { // 添加Content序列化特性 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Editor(typeof(CollectionEditor), typeof(UITypeEditor))] public NotifierList<int> Ints { get; set; } public YourCustomUserControl() { InitializeComponent(); Ints = new NotifierList<int>(); } } [Serializable] public class NotifierList<T> : List<T> { // 你的自定义集合逻辑 }
为什么需要这个特性?
- 原生
List<T>之所以能被设计器正常序列化,是因为.NET框架默认给它配置了Content级别的序列化规则——设计器会自动序列化集合内部的元素,而非集合对象的引用 - 对于自定义的
List<T>子类,设计器默认会将其视为普通引用类型,只会尝试序列化对象引用。但由于集合是在控件构造函数中初始化的,设计器无法追踪到引用的变更,因此不会生成任何序列化代码 DesignerSerializationVisibility.Content明确告诉设计器:需要序列化的是这个属性的内容(集合元素),而不是属性本身的引用。这样设计器才会将集合元素的修改写入Designer文件,实现持久化
关于ObservableCollection的序列化问题
ObservableCollection依赖System.Collections.ObjectModel.SimpleMonitor实现线程安全的变更通知,但这个类型并未标记为可序列化,因此在设计器序列化场景下会抛出“无法加载SimpleMonitor类型”的错误,无法直接用于需要设计器持久化的集合属性。
内容的提问来源于stack exchange,提问作者Choosechee
相关产品推荐
相关产品推荐

