User Control Property that shows a list of all For

2020-03-30 05:26发布

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条回答
女痞
2楼-- · 2020-03-30 05:51

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

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:

enter image description here

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);
    }
}
查看更多
登录 后发表回答