13

I have a class with a set of properties As given below.

class ContactInfo
{
    [ReadOnly(true)]
    [Category("Contact Info")]
    public string Mobile { get; set; }

    [Category("Contact Info")]
    public string Name{ get; set; }
}

The objects of this class is being assigned to a property grid, so that the users can update an existing contact. you can see that Mobile is marked as ReadOnly.

But, when I want to add an entirely new Contact, I would want the users to be able to edit the contact Mobile also. For that I need to remove the Readonly property dynamically from the Type, before assigning the object to the property grid. Is it possible?

Mike Two
  • 43,135
  • 9
  • 81
  • 96
SysAdmin
  • 5,232
  • 7
  • 32
  • 34

5 Answers5

7

You can not remove the attribute at runtime, but you can use reflection to change the ReadOnly attribute's ReadOnly private backing field to False. Making it the equivalent of [ReadOnly(false)]

See this article for details:

http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html

Edit: fixed link

andreialecu
  • 3,469
  • 2
  • 25
  • 34
2

I have to agree w/ Omu; you're really talking about two classes (view models) in this case, to support your two different views. Something like

CreateContactViewModel and EditContactViewModel

Paul
  • 34,558
  • 9
  • 85
  • 118
1

it's not possible at the moment to remove attributes dinamycally (at runtime)

as a suggestion you can do 2 classes: one with the attributes and one without

Omu
  • 67,351
  • 88
  • 268
  • 400
  • 1
    There's no need to make 2 classes, reflection can be used to modify the boolean field of the ReadOnly attribute and change it to false (not read only). – andreialecu Mar 20 '10 at 13:37
1

The CodingLight.com blog moved to blogspot (the above link is broken). See http://codinglight.blogspot.com/2008/10/changing-attribute-parameters-at.html.

Moreover, SysAdmin's followup did not mention the [RefreshProperties(RefreshProperties.All)] attribute that seems to be necessary for an actually-working solution.

Finally, I believe that even David Morton (author of the quoted article) missed one very important thing: if the class (ContactInfo, in SysAdmin's followup example) does not have at least one property with the [ReadOnly] attribute defined at compile time, then when the "isReadOnly" FieldInfo is set to true at runtime the result is that the whole class turns read-only.

Esailija
  • 134,577
  • 23
  • 263
  • 318
Mau
  • 136
  • 1
  • 5
0

I followed up the suggestion by Legenden. Here is what I came up with

class ContactInfo
{
        [ReadOnly(true)]
        [Category("Contact Info")]
        public string Mobile { get; set; }

        [Category("Contact Info")]
        public string Name{ get; set; }

        public void SetMobileEdit(bool allowEdit)
        {
             PropertyDescriptor descriptor =  TypeDescriptor.GetProperties(this.GetType())["Mobile"];

             ReadOnlyAttribute attrib = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];

             FieldInfo isReadOnly = attrib.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);

             isReadOnly.SetValue(attrib, !allowEdit);
        }
}
SysAdmin
  • 5,232
  • 7
  • 32
  • 34
  • I think that while this works, it's not a good design. The responsibilities are bleeding. – Paul Mar 20 '10 at 13:58