Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在运行时将DisplayNameAttribute更改为在属性网格C中使用#_C#_Propertygrid - Fatal编程技术网

C# 如何在运行时将DisplayNameAttribute更改为在属性网格C中使用#

C# 如何在运行时将DisplayNameAttribute更改为在属性网格C中使用#,c#,propertygrid,C#,Propertygrid,我想知道如何在运行时更改displayName属性,当我进行一些转换时,我希望displayName在我的属性网格中是英尺而不是米,这可能吗 [DisplayName("Meters")] public double Distance { get{return distance;} } 属性是作为类型的一部分编译的,因此不能在运行时更改它们 另一种解决方案是确定一个内部度量单位,您总是存储所有值。米是一个很好的候选人。然后创建“translator”服务,它位于您的consu

我想知道如何在运行时更改displayName属性,当我进行一些转换时,我希望displayName在我的属性网格中是英尺而不是米,这可能吗

[DisplayName("Meters")]
public double Distance
  {
     get{return distance;}
  }

属性是作为类型的一部分编译的,因此不能在运行时更改它们


另一种解决方案是确定一个内部度量单位,您总是存储所有值。米是一个很好的候选人。然后创建“translator”服务,它位于您的consumer类和原始类之间,负责将所有值转换为不同的格式。

在显示名称中设置单位有点奇怪,但如果这确实是您想要做的,然后,您唯一的解决方案是使用自定义PropertyDescriptor发布属性(感谢TypeConverter或自定义类型描述符),并覆盖DisplayName属性


这里也回答:

我不知道这是否有效,但您的DisplayName是一个属性。每个类和每个类的成员都可以设置属性。也就是说,PropertyInfo将为您提供访问此属性的权限。现在,如果你走这条路,访问PropertyInfo.GetCustomAttributes()或类似的东西,然后检索属性值,你说它是只读的,就像你对Nick说的那样吗?

有很多不同的方法可以做到这一点。最简单的方法是做一些类似于某些i18n产品的事情——对属性进行子类化并截取文本;但这仅在您拥有该类型并且无法从属性访问上下文的情况下才有效

接下来要看的是
TypeConverter
,因为这提供了对属性组件模型视图的访问,并且比下面两个选项更简单-p这将适用于
PropertyGrid
,但不适用于
DataGridView

列表中的下一个是
ICustomTypeDescriptor
——这不是一个有趣的接口,但您可以在自己的属性描述符中进行交换。这要求您拥有该类型(以便提供接口支持)

最后,
CustomTypeDescriptor
与上一个类似,但即使对于您不拥有的类型也有效,并且允许在类型和对象级别访问经过调整的元数据(其他所有内容都只支持对象)

选择哪一个?我怀疑
TypeConverter
将是最明智的选择;您需要对象上下文(子类属性不提供该上下文),但不需要额外的复杂性

这里有一个例子;请注意,在
TypeConverter
代码中,我们可以访问对象上下文。如果名称很简单,那么将其放入
TypeConverter
(创建属性时)就足够了

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
class MyFunkyTypeConverter : ExpandableObjectConverter
{
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        PropertyDescriptorCollection props = base.GetProperties(context, value, attributes);
        List<PropertyDescriptor> list = new List<PropertyDescriptor>(props.Count);
        foreach (PropertyDescriptor prop in props)
        {
            switch (prop.Name)
            {
                case "Distance":
                    list.Add(new DisplayNamePropertyDescriptor(
                        prop, "your magic code here"));
                    break;
                default:
                    list.Add(prop);
                    break;
            }
        }
        return new PropertyDescriptorCollection(list.ToArray(), true);
    }
}
class DisplayNamePropertyDescriptor : PropertyDescriptor
{
    private readonly string displayName;
    private readonly PropertyDescriptor parent;
    public DisplayNamePropertyDescriptor(
        PropertyDescriptor parent, string displayName) : base(parent)
    {
        this.displayName = displayName;
        this.parent = parent;
    }
    public override string  DisplayName
    {get { return displayName; } }

    public override bool ShouldSerializeValue(object component)
    { return parent.ShouldSerializeValue(component); }

    public override void SetValue(object component, object value) {
        parent.SetValue(component, value);
    }
    public override object GetValue(object component)
    {
        return parent.GetValue(component);
    }
    public override void ResetValue(object component)
    {
        parent.ResetValue(component);
    }
    public override bool CanResetValue(object component)
    {
        return parent.CanResetValue(component);
    }
    public override bool IsReadOnly
    {
        get { return parent.IsReadOnly; }
    }
    public override void AddValueChanged(object component, EventHandler handler)
    {
        parent.AddValueChanged(component, handler);
    }
    public override void RemoveValueChanged(object component, EventHandler handler)
    {
        parent.RemoveValueChanged(component, handler);
    }
    public override bool SupportsChangeEvents
    {
        get { return parent.SupportsChangeEvents; }
    }
    public override Type PropertyType
    {
        get { return parent.PropertyType; }
    }
    public override TypeConverter Converter
    {
        get { return parent.Converter; }
    }
    public override Type ComponentType
    {
        get { return parent.ComponentType; }
    }
    public override string Description
    {
        get { return parent.Description; }
    }
    public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)
    {
        return parent.GetChildProperties(instance, filter);
    }
    public override string Name
    {
        get { return parent.Name; }
    }

}

[TypeConverter(typeof(MyFunkyTypeConverter))]
class MyFunkyType
{
    public double Distance {get;set;}

    public double AnotherProperty { get; set; }
}
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form { Controls = {
            new PropertyGrid { Dock = DockStyle.Fill,
                SelectedObject = new MyFunkyType {
                    Distance = 123.45
                }}
        }});
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Windows.Forms;
类MyFunkyTypeConverter:ExpandableObjectConverter
{
公共重写属性描述或集合GetProperties(ITypeDescriptorContext上下文、对象值、属性[]属性)
{
PropertyDescriptorCollection props=base.GetProperties(上下文、值、属性);
列表=新列表(道具计数);
foreach(PropertyDescriptor道具中的道具)
{
开关(道具名称)
{
案例“距离”:
添加(新的DisplayNamePropertyDescriptor)(
道具,“这里是你的魔法代码”);
打破
违约:
列表。添加(道具);
打破
}
}
返回新的PropertyDescriptorCollection(list.ToArray(),true);
}
}
类DisplayNamePropertyDescriptor:PropertyDescriptor
{
私有只读字符串displayName;
私有只读属性描述器父级;
公共DisplayNamePropertyDescriptor(
PropertyDescriptor父级,字符串displayName):基(父级)
{
this.displayName=displayName;
this.parent=parent;
}
公共重写字符串DisplayName
{get{return displayName;}}
公共重写bool ShouldSerializeValue(对象组件)
{返回父级.ShouldSerializeValue(组件);}
公共覆盖无效设置值(对象组件、对象值){
父.SetValue(组件、值);
}
公共覆盖对象GetValue(对象组件)
{
返回parent.GetValue(组件);
}
公共替代无效重置值(对象组件)
{
父项。重置值(组件);
}
公共覆盖布尔CanResetValue(对象组件)
{
返回parent.CanResetValue(组件);
}
公共覆盖布尔为只读
{
获取{return parent.IsReadOnly;}
}
public override void AddValueChanged(对象组件、事件处理程序)
{
parent.AddValueChanged(组件、处理程序);
}
public override void RemoveValueChanged(对象组件、事件处理程序)
{
parent.RemoveValueChanged(组件、处理程序);
}
公共覆盖布尔支持SchangeEvents
{
获取{return parent.SupportsChangeEvents;}
}
公共覆盖类型PropertyType
{
获取{return parent.PropertyType;}
}
公共覆盖类型转换器
{
获取{return parent.Converter;}
}
公共重写类型ComponentType
{
获取{return parent.ComponentType;}
}
公共重写字符串描述
{
获取{return parent.Description;}
}
公共重写属性DescriptorCollection GetChildProperties(对象实例,属性[]筛选器)
{
返回parent.GetChildProperties(实例,过滤器);
}
公共重写字符串名
{
获取{return parent.Name;}
}
}
[TypeConverter(typeof(MyFunkyTypeConverter))]
类MyFunkyType
{
公共双距离{get;set;}
公共厕所