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

こ雲淡風輕ζ 提交于 2019-12-19 10:16:22

问题


As we all know Forms created with Form.cs file

I have property of type Form

example : public Form TargetForm {get;set;}

i don't need to use Activiator.CreateInstance() to create Form I just need to choose a Form from Forms.cs files and attach it with property of TargetForm .

See Screenshot http://prntscr.com/pmuxdd

Tips i guess maybe something usefull to readers : TypeDescriptors, Attributes maybe that return a list of classes in Visual Studio Solutions.

As we all know the ComponentModel API is hard to deal with. so please don't feel bad about that.


回答1:


There are two services that can help you at design-time to discover and resolve all types in the solution:

  • ITypeDiscoveryService: Discovers available types at design time.

  • ITypeResolutionService: Provides an interface to retrieve an assembly or type by name.

In the other hand, to show standard values in a dropdown in property editor, you can create a TypeConverter:

  • TypeConverter: Provides a unified way of converting types of values to other types, as well as for accessing standard values and subproperties.

Knowing about above options, you can create a custom type converter to discover all form types in the project and list in the dropdown.

Example

In the following example, I've created a custom button class which allows you to select a form type in design type and then at run-time, if you click on the button it shows the selected form as dialog:

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

MyButton

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


来源:https://stackoverflow.com/questions/58514948/user-control-property-that-shows-a-list-of-all-forms-at-design-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!