让设计器为 UserControl 的简单 List 属性生成 AddRange [英] Get designer to generate AddRange for simple List property of UserControl

查看:23
本文介绍了让设计器为 UserControl 的简单 List 属性生成 AddRange的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个新的 UserControl,如下所示:

I have created a new UserControl like so:

    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 类只包含两个 get/set 属性,没有别的:

The Fruit class simply contains two get/set properties and nothing else:

public class Fruit {
    public bool Edible {
        get;
        set;
    }

    public string Name {
        get;
        set;
    }
}

当我从窗体上的 Visual Studio 工具箱中拖动 MyControl 的一个实例,然后使用 Visual Studio 设计器继续将 Fruit 对象添加到 MyControl 的 Fruits 集合时,我希望设计器生成新的 Fruit 实例,并通过生成对集合 AddRange<的调用,自动将它们添加到设计器生成的代码中的 Fruits 集合中/code> 或 Add 方法.

When I drag an instance of MyControl from the Visual Studio toolbox on a Form and then proceed to add Fruit objects to the Fruits collection of MyControl using the Visual Studio designer, I expected the designer to generate new Fruit instances and automatically add them to the Fruits collection in the designer-generated code by generating a call to the collections AddRange or Add method.

但是它不会生成任何 AddRange 代码来将它们添加到 MyControlFruits 集合中,所以我最终徘徊"Fruit 代码隐藏中的实例.我已经尝试将 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 属性添加到 Fruits 属性,但没有任何效果.我错过了什么?

However it does not generate any AddRange code to add them to MyControl's Fruits collection and so I end up with "lingering" Fruit instances in the code-behind. I already tried adding the [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] attribute to the Fruits property, but that did nothing. What am I missing?

推荐答案

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]Fruits 需要让设计师知道序列化它的内容.此外 Fruits 属性不需要公共设置器:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] is needed for Fruits to let the designer know to serialize its content. Also the Fruits property doesn't need a 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);

更简洁的设计器生成的代码

如果您想生成更清晰的代码,如下所示:

If you want to have a cleaner code generated, like following:

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 用于使用 InstanceDescriptor 创建类的实例:

You need to create a TypeConverter for your Fruit class which uses InstanceDescriptor to create an instance of the 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);
    }
}

这篇关于让设计器为 UserControl 的简单 List 属性生成 AddRange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆