我在.NET中有一个用户控件,有2个新属性
Prop1: Boolean
Prop2: String
当用户将 Prop1 设置为 false 时,我想在属性网格中设置 Prop2 READONLY 。< / p>
答案 0 :(得分:6)
如果要根据某些条件在运行时使属性外观为只读(灰色),则需要为您的类分配CustomTypeDescriptor
,该类提供有关属性网格的类的元数据。
PropertyGrid
控件使用对象的类型描述符来提取有关其属性的信息以显示。类型描述符返回PropertyDescriptor
个对象的列表作为属性列表。每个PropertyDescriptor
都包含一些方法和属性,用于返回显示名称,描述以及有关该属性的其他信息。 IsReadOnly
的{{1}}属性负责通知PropertyDescriptor
该属性是否应该只读。
示例强>
在下面的示例中,我创建了一个包含两个属性的类。 PropertyGrid
和Editable
。如果StringProperty
为Editable
,那么true
是可编辑的,否则它将是只读的,并会在StringProperty
中显示为灰色。
<强> MyPropertyDescriptor 强>
它负责提供财产的元数据。实现此类时,对于大多数属性,我们将使用使用原始属性实现的简单实现,但对于PropertyGrid
,我们将根据所有者对象的IsReadOnly
属性的值来决定:
Editable
<强> MyTypeDescriptor 强>
负责提供对象的属性列表。对于我们将在运行时更改其行为的using System;
using System.ComponentModel;
using System.Linq;
public class MyPropertyDescriptor : PropertyDescriptor
{
PropertyDescriptor p;
SampleClass o;
public MyPropertyDescriptor(PropertyDescriptor originalProperty, SampleClass owenr)
: base(originalProperty) { p = originalProperty; o = owenr; }
public override bool CanResetValue(object component)
{ return p.CanResetValue(component); }
public override object GetValue(object component) { return p.GetValue(component); }
public override void ResetValue(object component) { p.ResetValue(component); }
public override void SetValue(object component, object value)
{ p.SetValue(component, value); }
public override bool ShouldSerializeValue(object component)
{ return p.ShouldSerializeValue(component); }
public override AttributeCollection Attributes { get { return p.Attributes; } }
public override Type ComponentType { get { return p.ComponentType; } }
public override bool IsReadOnly { get { return !o.Editable; } }
public override Type PropertyType { get { return p.PropertyType; } }
}
,我们将返回StringProperty
:
MyPropertyDescriptor
<强> MyTypeDescriptionProvider 强>
当某人(如属性网格)请求类型描述时,它负责返回对象的类型描述符:
using System;
using System.ComponentModel;
using System.Linq;
public class MyTypeDescriptor : CustomTypeDescriptor
{
ICustomTypeDescriptor d;
SampleClass o;
public MyTypeDescriptor(ICustomTypeDescriptor originalDescriptor, SampleClass owner)
: base(originalDescriptor) { d = originalDescriptor; o = owner; }
public override PropertyDescriptorCollection GetProperties()
{ return this.GetProperties(new Attribute[] { }); }
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
.Select(p => p.Name == "StringProperty" ? new MyPropertyDescriptor(p, o) : p)
.ToArray();
return new PropertyDescriptorCollection(properties);
}
}
<强> SampleClass 强>
最后,该类的实现:
using System;
using System.ComponentModel;
public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
public MyTypeDescriptionProvider()
: base(TypeDescriptor.GetProvider(typeof(object))) { }
public override ICustomTypeDescriptor GetTypeDescriptor(Type type, object o)
{
ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(type, o);
return new MyTypeDescriptor(baseDescriptor, (SampleClass)o);
}
}
<强>结果强>
进一步阅读
您可以在以下帖子中阅读其他一些解决方案:
答案 1 :(得分:0)
非常感谢@ reza-aghaei, 根据您的详细答案和@Ivan评论,以下片段解决了我的问题:
Dim captionFld = TypeDescriptor.GetProperties(Me)("Caption")
Dim roaCaption = captionFld.Attributes.OfType(Of ReadOnlyAttribute)().FirstOrDefault
roaCaption.GetType().GetField("isReadOnly", BindingFlags.NonPublic Or BindingFlags.Instance).SetValue(roaCaption, True)
或C#
var captionFld = TypeDescriptor.GetProperties(this)["Caption"];
var roaCaption = captionFld.Attributes.OfType(Of, ReadOnlyAttribute)[].FirstOrDefault;
roaCaption.GetType().GetField("isReadOnly", (BindingFlags.NonPublic | BindingFlags.Instance)).SetValue(roaCaption, true);
您可以更改 .SetValue(roaCaption,true | false);
非常感谢。
答案 2 :(得分:0)
请确保您在名为&#34;可编辑&#34;
的媒体资源上拥有以下属性[RefreshProperties(System.ComponentModel.RefreshProperties.All)]
添加以下方法,并从&#34;可编辑&#34;的设置器中调用它。属性并传递属性的名称以设置为只读。
public void EnableDisableProperty(string PropertyName,bool IsReadOnly)
{
PropertyDescriptor _propDescriptor = TypeDescriptor.GetProperties(this.GetType())[PropertyName];
ReadOnlyAttribute _readOnlyAttribute = (ReadOnlyAttribute)
_propDescriptor.Attributes[typeof(ReadOnlyAttribute)];
FieldInfo _fieldToChange = _readOnlyAttribute.GetType().GetField("isReadOnly",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
_fieldToChange.SetValue(_readOnlyAttribute, IsReadOnly);
}