如何在运行时更改 DisplayNameAttribute 以在属性网格 C# 中使用
我想知道如何在运行时更改 DisplayNameAttribute,当我进行一些转换时,我希望属性网格中的 displayName 为英尺而不是米,这可能吗?
[DisplayName("Meters")]
public double Distance
{
get{return distance;}
}
I am wondering how to change the DisplayNameAttribute on runtime, I want the displayName to be Feet instead of Meters in my property grid when I do some conversions, is that possible?
[DisplayName("Meters")]
public double Distance
{
get{return distance;}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
有多种不同的方法可以做到这一点。最简单的方法是执行类似于某些 i18n 产品的操作方式 - 子类化属性并拦截文本;但这仅在您拥有该类型时才有效,并且您无法从属性访问上下文。
接下来要考虑的是 TypeConverter,因为它提供了对属性的组件模型视图的访问,并且比接下来的两个选项更简单;-p 这将与 PropertyGrid 一起使用,但不是
DataGridView
等。列表中的下一个是
ICustomTypeDescriptor
- 不是一个有趣的实现接口,但您可以交换自己的属性描述符。这要求您拥有该类型(以便提供接口支持)。最后,
CustomTypeDescriptor
与最后一个类似,但甚至适用于您不拥有的类型,并且允许访问类型和对象处的调整元数据em> 级别(其他所有内容仅支持对象)。选择哪个?我怀疑 TypeConverter 是最明智的;您需要对象上下文(子类属性不提供),但不需要额外的复杂性。
这是一个例子;请注意,在
TypeConverter
代码中,我们可以访问对象上下文。如果名称很简单,那么将其放入TypeConverter
(创建属性时)就足够了。There are a number of different ways to do this. The simplest is to do something akin to how certain i18n products do it - subclass the attribute and intercept the text; but this only works if you own the type, and from an attribute you can't access the context.
The next things to look at would be
TypeConverter
, since this provides access to the component-model view on the properties, and is simpler than the next two options ;-p This will work withPropertyGrid
, but notDataGridView
etc.Next on the list is
ICustomTypeDescriptor
- not a fun interface to implement, but you can swap in your own property-descriptor. This requires that you own the type (in order to provide the interface support).Finally,
CustomTypeDescriptor
is like the last, but works even for types you don't own, and allows access to tweaked metadata at both the type and object level (everything else only supports object).Which to choose? I suspect that
TypeConverter
would be the most sensible; you need the object-context (which a subclassed attribute doesn't provide), but you don't need the extra complexity.Here's an example; note that in the
TypeConverter
code we have access to the object-context. If the name is simple, then putting it in theTypeConverter
(when creating the property) should suffice.如果displayname属性已经存在(像这种情况)并且您只想更改名称,则可以使用该属性的propertydescriptor。只需查看attributes 属性,直到找到该属性并更改其值。
If the displayname attribute already exists (like this situation) and you just want to change the name, you can use the propertydescriptor of this property. Just look through the attributes property until you find the attribute and change the value.
属性被编译为类型的一部分,因此无法在运行时更改。
另一种解决方案可能是确定始终存储所有值的内部测量单位。米是一个不错的候选人。然后创建位于您的消费者类和原始类之间的“翻译器”服务,该服务负责将所有值转换为不同的格式。
Attributes are compiled as part of the type, so they cannot be changed at runtime.
An alternative solution could be to determine an internal unit of measure which you always store all values. Meters is a good candidate. Then create "translator" services which sit between your consumer class and the original class, which is responsible for converting all the values to a different format.
在显示名称中设置单位有点奇怪,但如果这确实是您想要做的,那么您唯一的解决方案是使用自定义 PropertyDescriptor 发布属性(感谢 TypeConverter 或自定义类型描述符)并覆盖 DisplayName 属性。
也在这里回答:更改属性的 DisplayName 属性
It is a bit odd to set the unit in the display name, but if this is really what you want to do, then your only solution is to publish your properties with custom PropertyDescriptors (thanks to a TypeConverter or a custom Type Descriptor) and to override the DisplayName property.
Answered here too: Change DisplayName attribute for a property
我不知道这是否有效,但您的 DisplayName 是一个属性。每个类和每个类的成员可以具有属性集。也就是说,PropertyInfo 将使您能够访问此属性,这是有道理的。现在,如果您走这条路并遇到 PropertyInfo.GetCustomAttributes() 或类似的东西,并且您检索您的属性值,那么您是否像您对尼克所说的那样说它是只读的?
I don't know if this will work, but your DisplayName is an Attribute. Each class and each class' members may have attributes set. That said, it makes sens that the PropertyInfo will give you acces to this Attribute. Now, if you go this way and come accross PropertyInfo.GetCustomAttributes() or something like it, and you retrieve your Attribute value, is that it you say that is read-only as you said to Nick?