让设计器为 UserControl 的简单列表 属性 生成 AddRange
Get designer to generate AddRange for simple List property of UserControl
我像这样创建了一个新的用户控件:
public partial class MyControl : UserControl {
List<Fruit> _fruits = new List<Fruit>();
public List<Fruit> Fruits {
get {
return _fruits;
}
set {
_fruits = value;
}
}
public UserControl1() {
InitializeComponent();
}
}
Fruit
class 仅包含两个 get/set 属性,仅包含:
public class Fruit {
public bool Edible {
get;
set;
}
public string Name {
get;
set;
}
}
当我从窗体上的 Visual Studio 工具箱中拖动 MyControl 的一个实例,然后使用 Visual Studio 设计师,我希望设计师生成新的 Fruit
实例,并通过生成对集合 AddRange
或 [=19] 的调用,自动将它们添加到设计师生成的代码中的 Fruits
集合中=]方法。
但是它不会生成任何 AddRange
代码来将它们添加到 MyControl
的 Fruits
集合中,所以我最终得到 "lingering" Fruit
代码隐藏中的实例。我已经尝试将 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
属性添加到 Fruits
属性,但没有任何效果。我错过了什么?
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
需要 Fruits
让设计者知道序列化它的内容。 Fruits
属性 也不需要 public setter:
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
public partial class MyControl : UserControl
{
public MyControl()
{
Fruits = new List<Fruit>();
InitializeComponent();
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Fruit> Fruits { get; private set; }
}
结果将生成以下代码:
Sample.Fruit fruit1 = new Sample.Fruit();
Sample.Fruit fruit2 = new Sample.Fruit();
Sample.Fruit fruit3 = new Sample.Fruit();
this.myControl1 = new Sample.MyControl();
//
// myControl1
//
fruit1.Edible = true;
fruit1.Name = "Apple";
fruit2.Edible = true;
fruit2.Name = "Orange";
fruit3.Edible = true;
fruit3.Name = "Banana";
this.myControl1.Fruits.Add(fruit1);
this.myControl1.Fruits.Add(fruit2);
this.myControl1.Fruits.Add(fruit3);
更干净的设计器生成的代码
如果您想生成更清晰的代码,如下所示:
this.myControl1 = new Sample.MyControl();
//
// myControl1
//
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Apple"));
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Orange"));
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Banana"));
您需要创建一个 TypeConverter
for your Fruit
class which uses InstanceDescriptor
来创建 class 的实例:
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
[TypeConverter(typeof(FruitConverter))]
public class Fruit
{
public Fruit() { }
public Fruit(bool edible, string name) : this()
{
Edible = edible;
Name = name;
}
public bool Edible { get; set; }
public string Name { get; set; }
}
public class FruitConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor)) {
var ci = typeof(Fruit).GetConstructor(new Type[] {
typeof(bool), typeof(string) });
var t = (Fruit)value;
return new InstanceDescriptor(ci, new object[] { t.Edible, t.Name });
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
我像这样创建了一个新的用户控件:
public partial class MyControl : UserControl {
List<Fruit> _fruits = new List<Fruit>();
public List<Fruit> Fruits {
get {
return _fruits;
}
set {
_fruits = value;
}
}
public UserControl1() {
InitializeComponent();
}
}
Fruit
class 仅包含两个 get/set 属性,仅包含:
public class Fruit {
public bool Edible {
get;
set;
}
public string Name {
get;
set;
}
}
当我从窗体上的 Visual Studio 工具箱中拖动 MyControl 的一个实例,然后使用 Visual Studio 设计师,我希望设计师生成新的 Fruit
实例,并通过生成对集合 AddRange
或 [=19] 的调用,自动将它们添加到设计师生成的代码中的 Fruits
集合中=]方法。
但是它不会生成任何 AddRange
代码来将它们添加到 MyControl
的 Fruits
集合中,所以我最终得到 "lingering" Fruit
代码隐藏中的实例。我已经尝试将 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
属性添加到 Fruits
属性,但没有任何效果。我错过了什么?
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
需要 Fruits
让设计者知道序列化它的内容。 Fruits
属性 也不需要 public setter:
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
public partial class MyControl : UserControl
{
public MyControl()
{
Fruits = new List<Fruit>();
InitializeComponent();
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Fruit> Fruits { get; private set; }
}
结果将生成以下代码:
Sample.Fruit fruit1 = new Sample.Fruit();
Sample.Fruit fruit2 = new Sample.Fruit();
Sample.Fruit fruit3 = new Sample.Fruit();
this.myControl1 = new Sample.MyControl();
//
// myControl1
//
fruit1.Edible = true;
fruit1.Name = "Apple";
fruit2.Edible = true;
fruit2.Name = "Orange";
fruit3.Edible = true;
fruit3.Name = "Banana";
this.myControl1.Fruits.Add(fruit1);
this.myControl1.Fruits.Add(fruit2);
this.myControl1.Fruits.Add(fruit3);
更干净的设计器生成的代码
如果您想生成更清晰的代码,如下所示:
this.myControl1 = new Sample.MyControl();
//
// myControl1
//
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Apple"));
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Orange"));
this.myControl1.Fruits.Add(new Sample.Fruit(true, "Banana"));
您需要创建一个 TypeConverter
for your Fruit
class which uses InstanceDescriptor
来创建 class 的实例:
using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
[TypeConverter(typeof(FruitConverter))]
public class Fruit
{
public Fruit() { }
public Fruit(bool edible, string name) : this()
{
Edible = edible;
Name = name;
}
public bool Edible { get; set; }
public string Name { get; set; }
}
public class FruitConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor)) return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor)) {
var ci = typeof(Fruit).GetConstructor(new Type[] {
typeof(bool), typeof(string) });
var t = (Fruit)value;
return new InstanceDescriptor(ci, new object[] { t.Edible, t.Name });
}
return base.ConvertTo(context, culture, value, destinationType);
}
}