Remove C# attribute of a property dynamically
Asked Answered
H

6

15

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?

Huffman answered 20/3, 2010 at 13:11 Comment(0)
B
11

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

Bromism answered 20/3, 2010 at 13:31 Comment(3)
Link in answer is dead - "404 Not Found".Toon
link is no longer validBriefs
The article is available through the Waback Machine: web.archive.org/web/20190907182632/http://…Autum
C
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

Calendre answered 20/3, 2010 at 13:26 Comment(0)
C
2

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.

Circle answered 7/11, 2010 at 16:21 Comment(1)
New link is also broken.Hannah
G
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

Geraint answered 20/3, 2010 at 13:14 Comment(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).Bromism
H
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);
        }
}
Huffman answered 20/3, 2010 at 13:49 Comment(1)
I think that while this works, it's not a good design. The responsibilities are bleeding.Calendre
R
0

And the original "link" show this: enter image description here

Now the link won't break again

Rozellarozelle answered 30/3, 2023 at 10:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.