c# - 让设计者为 UserControl 的简单 List 属性生成 AddRange

标签 c# visual-studio winforms user-controls windows-forms-designer

我创建了一个新的用户控件,如下所示:

    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 类仅包含两个获取/设置属性,仅包含其他内容:

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

    public string Name {
        get;
        set;
    }
}

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

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

最佳答案

Fruits 需要

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 来让设计器知道序列化其内容。此外,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对于使用 InstanceDescriptorFruit 类创建类的实例:

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);
    }
}

关于c# - 让设计者为 UserControl 的简单 List 属性生成 AddRange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51580202/

相关文章:

c# - 为什么我的 C# WPF 程序在 Application.Shutdown() 之后继续执行行?

c++ - MFC 应用程序中 Delphi 7 和 Delphi XE4 之间的 ActiveX 差异

visual-studio - 我可以阻止 Visual Studio 2012+ 发布packages.config 和EF 图表文件吗?

c# - 自定义标签不显示文本字符串

c# - 使用 Builder 类通过 DI 重新创建子对象集?

C# Enumerable.Except() 只返回一次相同的元素

c# - ref 或 out 参数必须是可赋值变量?

c# - 如何在 C# 中的特定时间生成警报?

c# - 如何使用双显示器应用程序解决这个焦点问题?

asp.net - 如何在Visual Studio 2019中创建ASP.NET网站?