.Net如何为用户控件的属性设置IsReadOnly

时间:2018-01-20 19:08:20

标签: c# .net vb.net winforms user-controls

我在.NET中有一个用户控件,有2个新属性

Prop1: Boolean
Prop2: String

当用户将 Prop1 设置为 false 时,我想在属性网格中设置 Prop2 READONLY 。< / p>

enter image description here

3 个答案:

答案 0 :(得分:6)

如果要根据某些条件在运行时使属性外观为只读(灰色),则需要为您的类分配CustomTypeDescriptor,该类提供有关属性网格的类的元数据。

PropertyGrid控件使用对象的类型描述符来提取有关其属性的信息以显示。类型描述符返回PropertyDescriptor个对象的列表作为属性列表。每个PropertyDescriptor都包含一些方法和属性,用于返回显示名称,描述以及有关该属性的其他信息。 IsReadOnly的{​​{1}}属性负责通知PropertyDescriptor该属性是否应该只读。

示例

在下面的示例中,我创建了一个包含两个属性的类。 PropertyGridEditable。如果StringPropertyEditable,那么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);
    }
}

<强>结果

enter image description here

进一步阅读

您可以在以下帖子中阅读其他一些解决方案:

答案 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);
    }