在设计时显示所有表单列表的用户控件 属性

User Control Property that shows a list of all Forms at design time

众所周知,使用 Form.cs 文件创建的表单

我有 属性 类型 Form

示例:public Form TargetForm {get;set;}

我不需要使用 Activiator.CreateInstance() 来创建表单 我只需要从 Forms.cs 个文件中选择一个表单并将其附加到 属性 的 TargetForm 。

查看截图http://prntscr.com/pmuxdd

提示我想可能对读者有用: 类型描述符、属性可能是 return Visual Studio 解决方案中的 类 列表。

众所周知 ComponentModel API 很难处理。所以请不要为此感到难过。

有两种服务可以帮助您在设计时发现和解析解决方案中的所有类型:

另一方面,要在 属性 编辑器的下拉列表中显示标准值,您可以创建 TypeConverter:

  • TypeConverter提供将值类型转换为其他类型以及访问标准值和子属性的统一方法。

了解以上选项后,您可以创建一个自定义类型转换器来发现项目中的所有表单类型并在下拉列表中列出。

例子

在下面的示例中,我创建了一个自定义按钮 class,它允许您在设计类型中 select 表单类型,然后在 运行 时,如果您单击按钮,它将 selected 形式显示为对话框:

To see a VB.NET version for this answer see .

我的按钮

using System;
using System.ComponentModel;
using System.Windows.Forms;
public class MyButton : Button
{
    [TypeConverter(typeof(FormTypeConverter))]
    public Type Form { get; set; }

    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        if (Form != null && typeof(Form).IsAssignableFrom(Form))
        {
            using (var f = (Form)Activator.CreateInstance(Form))
                f.ShowDialog();
        }
    }
}

FormTypeConverter

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
public class FormTypeConverter : TypeConverter
{
    public override bool GetStandardValuesExclusive
        (ITypeDescriptorContext context)
    {
        return true;
    }
    public override bool CanConvertTo
        (ITypeDescriptorContext pContext, Type pDestinationType)
    {
        return base.CanConvertTo(pContext, pDestinationType);
    }
    public override object ConvertTo
        (ITypeDescriptorContext pContext, CultureInfo pCulture,
        object pValue, Type pDestinationType)
    {
        return base.ConvertTo(pContext, pCulture, pValue, pDestinationType);
    }
    public override bool CanConvertFrom(ITypeDescriptorContext pContext,
        Type pSourceType)
    {
        if (pSourceType == typeof(string))
            return true;
        return base.CanConvertFrom(pContext, pSourceType);
    }
    public override object ConvertFrom
        (ITypeDescriptorContext pContext, CultureInfo pCulture, object pValue)
    {
        if (pValue is string)
            return GetTypeFromName(pContext, (string)pValue);
        return base.ConvertFrom(pContext, pCulture, pValue);
    }

    public override bool GetStandardValuesSupported
        (ITypeDescriptorContext pContext)
    {
        return true;
    }
    public override StandardValuesCollection GetStandardValues
        (ITypeDescriptorContext pContext)
    {
        List<Type> types = GetProjectTypes(pContext);
        List<string> values = new List<string>();
        foreach (Type type in types)
            values.Add(type.FullName);

        values.Sort();
        return new StandardValuesCollection(values);
    }
    private List<Type> GetProjectTypes(IServiceProvider serviceProvider)
    {
        var typeDiscoverySvc = (ITypeDiscoveryService)serviceProvider
            .GetService(typeof(ITypeDiscoveryService));
        var types = typeDiscoverySvc.GetTypes(typeof(object), true)
            .Cast<Type>()
            .Where(item =>
                item.IsPublic &&
                typeof(Form).IsAssignableFrom(item) &&
                !item.FullName.StartsWith("System")
            ).ToList();
        return types;
    }
    private Type GetTypeFromName(IServiceProvider serviceProvider, string typeName)
    {
        ITypeResolutionService typeResolutionSvc = (ITypeResolutionService)serviceProvider
            .GetService(typeof(ITypeResolutionService));
        return typeResolutionSvc.GetType(typeName);
    }
}