通过C#中的Designtime下拉列表选择静态字段

时间:2015-11-17 14:11:08

标签: c# forms visual-studio-2015 typeconverter uitypeeditor

是否可以修改ComponentConverterTypeconverter,...以便我可以选择表单外的静态类中的“组件”?

当我创建自定义控件并添加ComponentControl类型的属性时,我会在设计器中找到一个下拉菜单,我可以在其中选择一个现有控件。

对所选对象的引用会自动添加到设计器代码中。

问题是,下拉列表只允许我选择在此表单中声明的​​组件或此表单继承的表单,但不包括其他表单或静态类。

但是我希望在我的解决方案中有一个特定的文件,我可以在一段时间内声明所有这些组件,然后在设计时在每个表单中使用它们(我的项目中有几个)。

Image of static declaring class

当我在设计器代码中自己添加对静态对象的引用时,一切正常,但这并不舒服,因为我必须手动更改代码。

screenshot of the designer code, last line

是否可以修改ConverterUITypeEditor,以便它可以选择静态对象然后将它们传递给设计师?

我试图覆盖ComponentConverter,但在设计器代码中它只写“null”而不是对象:

class MyConverter : ComponentConverter
{
    public MyConverter(Type type) : base(type)
    {
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(new List<BOOL>() { Variablen.M0_2, Variablen.M0_3, Variablen.M0_4 });
    }
}

1 个答案:

答案 0 :(得分:0)

经过一些工作,我得到了这个工作,但稳定性并不是最好的。有时在编译之后我会收到错误,因为TypeConverter

中的上下文或服务为空

基类:

[TypeConverter(typeof(MyReferenceTypeonverter))]
[DesignerSerializer(typeof(MyObjectSerializer), typeof(CodeDomSerializer))]
public abstract class MyReferencableObject
{
    internal FieldInfo FieldInfo { get; set; }

    //Could also use: FieldInfo.DeclaringType.FullName + "." + FieldInfo.Name;
    public string FullName { get { return FieldInfo.DeclaringType.Name + "." + FieldInfo.Name; } }
}

串行:

public class MyObjectSerializer : CodeDomSerializer
{
    public override object Serialize(IDesignerSerializationManager manager, object value)
    {
        return new CodeVariableReferenceExpression((value as MyReferencableObject).FullName);
    }
}`

容器

 /// <summary>
/// Prototype for class that whrer MyReferencableObject are declared
/// </summary>
public abstract class Deklaration
{

}

的TypeConverter

public class MyReferenceTypeonverter : TypeConverter
{
    private Type ContainerType = typeof(Deklaration);

    private const string empty = "(none)";


    Dictionary<string, MyReferencableObject> values;

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        return destinationType == typeof(string);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        string FullName = (string)value;

        if (FullName == empty)
            return null;

        InitDict(context);

        if (values.ContainsKey(FullName))
            return values[FullName];

        return value;
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (value == null)
            return empty;

        InitDict(context);

        foreach (string key in values.Keys)
            if (key != empty)
                if (values[key].FullName == ((MyReferencableObject)value).FullName)
                    return key;

        //sometimes happens...
        return "ERROR!!!";
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        InitDict(context);
        return new StandardValuesCollection(values.Values);
    }

    void InitDict(ITypeDescriptorContext context)
    {
        //sometimes happens...
        if (context == null)
            return;

        Dictionary<string, MyReferencableObject> tvalues = new Dictionary<string, MyReferencableObject>();
        tvalues.Add(empty, null);

        ITypeDiscoveryService Service = (ITypeDiscoveryService)context.GetService(typeof(ITypeDiscoveryService));

        //sometimes happens...
        if (Service == null)
            return;

        foreach (Type declaration in Service.GetTypes(ContainerType, false))
            foreach (FieldInfo fieldInfo in declaration.GetFields())
                if (context.PropertyDescriptor.PropertyType.IsAssignableFrom(fieldInfo.FieldType))
                {
                    MyReferencableObject var = (MyReferencableObject)fieldInfo.GetValue(null);
                    var.FieldInfo = fieldInfo;
                    tvalues.Add(var.FullName, var);
                }

        //in a perfect world the if should not be necessary....
        if (tvalues.Count > 1 || values == null)
            values = tvalues;
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        return TypeDescriptor.GetProperties(value, attributes);
    }
}