.Net 如何为用户控件的 属性 设置 IsReadOnly
.Net how to set IsReadOnly for a property for a usercontrol
我在 .NET 中有一个用户控件,其中有 2 个新 属性
Prop1: Boolean
Prop2: String
当用户设置 Prop1[ 时,我想在 属性 网格中使 Prop2 READONLY =23=] 到 false.
如果您想根据某些条件在 运行 时将 属性 外观设置为只读(灰色),您需要将 CustomTypeDescriptor
分配给您的 class 为 属性 网格提供有关 class 的元数据。
PropertyGrid
control uses the type descriptor of the object to extract information about its properties to show. The type descriptor, returns a list of PropertyDescriptor
个对象作为属性列表。每个 PropertyDescriptor
包含一些方法和属性以 return 显示名称、描述和有关 属性 的其他信息。 PropertyDescriptor
的 IsReadOnly
属性 负责通知 PropertyGrid
是否 属性 应该是只读的。
例子
在下面的示例中,我创建了一个包含两个属性的 class。 Editable
和 StringProperty
。如果 Editable
是 true
那么 StringProperty
是可编辑的,否则它将是只读的并且在 PropertyGrid
.
中显示为灰色
我的属性描述符
它负责为 属性 提供元数据。在实现此 class 时,对于大多数属性,我们将使用使用原始 属性 实现的简单实现,但对于 IsReadOnly
我们将根据 [=21= 的值来决定] 属性 所有者对象:
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
,我们将在 运行 时更改其行为,我们将 return a 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
它负责 return 你的对象的类型描述符,当有人(比如 属性 grid)请求类型描述时:
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);
}
}
样本类
最后,class的执行:
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;
}
}
}
结果
进一步阅读
您可以阅读以下内容中的一些其他解决方案 post:
非常感谢@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);
非常感谢。
请确保您在名为 "Editable"
的 属性 上具有以下属性
[RefreshProperties(System.ComponentModel.RefreshProperties.All)]
添加以下方法,并从"Editable"属性的setter调用它,并传递属性的名称以设置只读。
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);
}
我在 .NET 中有一个用户控件,其中有 2 个新 属性
Prop1: Boolean
Prop2: String
当用户设置 Prop1[ 时,我想在 属性 网格中使 Prop2 READONLY =23=] 到 false.
如果您想根据某些条件在 运行 时将 属性 外观设置为只读(灰色),您需要将 CustomTypeDescriptor
分配给您的 class 为 属性 网格提供有关 class 的元数据。
PropertyGrid
control uses the type descriptor of the object to extract information about its properties to show. The type descriptor, returns a list of PropertyDescriptor
个对象作为属性列表。每个 PropertyDescriptor
包含一些方法和属性以 return 显示名称、描述和有关 属性 的其他信息。 PropertyDescriptor
的 IsReadOnly
属性 负责通知 PropertyGrid
是否 属性 应该是只读的。
例子
在下面的示例中,我创建了一个包含两个属性的 class。 Editable
和 StringProperty
。如果 Editable
是 true
那么 StringProperty
是可编辑的,否则它将是只读的并且在 PropertyGrid
.
我的属性描述符
它负责为 属性 提供元数据。在实现此 class 时,对于大多数属性,我们将使用使用原始 属性 实现的简单实现,但对于 IsReadOnly
我们将根据 [=21= 的值来决定] 属性 所有者对象:
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
,我们将在 运行 时更改其行为,我们将 return a 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
它负责 return 你的对象的类型描述符,当有人(比如 属性 grid)请求类型描述时:
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);
}
}
样本类
最后,class的执行:
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;
}
}
}
结果
进一步阅读
您可以阅读以下内容中的一些其他解决方案 post:
非常感谢@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);
非常感谢。
请确保您在名为 "Editable"
的 属性 上具有以下属性[RefreshProperties(System.ComponentModel.RefreshProperties.All)]
添加以下方法,并从"Editable"属性的setter调用它,并传递属性的名称以设置只读。
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);
}