如果您想根据某些条件在运行时将属性外观设为只读(灰色),您需要为您的类分配一个CustomTypeDescriptor,它为属性网格提供有关您的类的元数据。
PropertyGrid 控件使用对象的类型描述符来提取有关其要显示的属性的信息。类型描述符返回 PropertyDescriptor 对象列表作为属性列表。每个PropertyDescriptor 都包含一些方法和属性,用于返回显示名称、描述和其他有关属性的信息。 PropertyDescriptor 的IsReadOnly 属性负责通知PropertyGrid 该属性是否为只读。
示例
在以下示例中,我创建了一个包含两个属性的类。 Editable 和 StringProperty。如果Editable 是true,那么StringProperty 是可编辑的,否则它将是只读的并且将在PropertyGrid 中显示为灰色。
MyPropertyDescriptor
它负责为属性提供元数据。在实现这个类时,对于大多数属性,我们将使用使用原始属性实现的普通实现,但对于IsReadOnly,我们将根据所有者对象的Editable属性的值来决定:
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; } }
}
MyTypeDescriptor
它负责提供对象的属性列表。对于StringProperty,我们将在运行时更改其行为,我们将返回MyPropertyDescriptor:
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);
}
}
MyTypeDescriptionProvider
当有人(如属性网格)请求类型描述时,它负责为您的对象返回类型描述符:
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);
}
}
SampleClass
最后是类的实现:
using System;
using System.ComponentModel;
[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]
public class SampleClass
{
[RefreshProperties(RefreshProperties.All)]
public bool Editable { get; set; }
string sp;
public string StringProperty
{
get { return sp; }
set
{
if (Editable)
sp = value;
}
}
}
结果
进一步阅读
您可以在以下帖子中了解其他一些解决方案: