在C#中的设计时通过下拉列表选择静态字段 [英] Selecting static fields via dropdown at Designtime in C#

查看:134
本文介绍了在C#中的设计时通过下拉列表选择静态字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以修改ComponentConverterTypeconverter,...,以便我可以选择表格之外的静态类中的组件"?

Is it possible to modify a ComponentConverter, Typeconverter,... so I can select "Components" that are in a static class outside the form?

当我创建一个自定义控件并添加类型为ComponentControl的属性时,我在设计器中获得了一个下拉菜单,可以从中选择一个或多个现有菜单.

When I create a custom control and add a property of type Component or Control I get a dropdown menu in designer where I can select one ot the existing ones.

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

The reference to the selected object is automatically added in the designer code.

问题是,该下拉列表仅允许我选择以此形式声明的组件或该形式继承的形式,而不能选择其他形式或静态类.

Problem is, that the dropdown only lets me select components that were declared in this form or a form that this form inherits, but no other form or a static class.

但是我想在解决方案中有一个特定的文件,我可以一次声明所有这些组件,然后在设计时以每种形式使用它们(我的项目中有多个).

But I want to have one specific file in my solution where I can declare all these components once, an then use them in each form (I have several in my project) at designtime.

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

When I add the reference to the static objects myself in designer code, everything works fine, but this is not comfortable, because I have to alter the code manually.

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

Would it be possible to modify a Converter or UITypeEditor, so it can select static objects and then pass them to the designer?

我尝试覆盖ComponentConverter,但是在设计器代码中,它仅写"null"而不是对象:

I tried to override a ComponentConverter, but in the designer code it only writes "null" instead of the object:

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

推荐答案

经过一些工作,我可以正常工作,但是稳定性并不是最好的.有时在编译后会出现错误,因为TypeConverter

After some work, I got this working, but stability is not the best. Sometimes after compiling I get errors, because context or service is null in the 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

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

这篇关于在C#中的设计时通过下拉列表选择静态字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆