locked
Adding BrowsableAttribute(false) to <property> causes <property>.ShouldSerializeValue(value) to return false RRS feed

  • Question

  • The particular property that I am having trouble with is the property 'Tag' of 'System.Windows.Forms.Control', so this is not a custom property or object of any sort.
     
     I've implemented the ITypeDescriptorFilterService to filter out specific properties from the property grid (of a custom extension of DesignSurfaceManager). Within my implementation in FilterProperties, I added the attribute BrowsableAttribute(false) to each property I wish to hide in the property grid. This gets the desired effect of removing it from the property grid, however, at the point of trying to serialize the form designed on the surface, the <property>.ShouldSerializeValue(<the control>) returns false, and thus it's not serialized (if this returns false it doesn't attempt to .GetValue).
     
    If I were to ignore the check for ShouldSerializeValue() when the property is Tag, the <property>.GetValue(<control>) throws an error (as expected) of 
    Property accessor 'Tag' on object 'TextBox1' threw the following exception:'Accessor methods for the [...]HostTypeDescriptorFilterService.Tag property are missing.'
    If I go to my list of properties that I wish to hide, and remove 'Tag' from that list. Everything works as expected, except 'Tag' is (of course) visible in the property grid, which is not desirable.
     
    The code that I'm using to add the BrowsableAttribute(false) is as follows
    private IDictionary HidePropertiesInDesigner(string[] propertiesToHide, IDictionary properties)
    {
         foreach (string propname in propertiesToHide)
         {
              PropertyDescriptor prop = (PropertyDescriptor)properties[propname];
              if (prop != null)
              {
    
                   AttributeCollection runtimeAttributes = prop.Attributes;
                   Attribute[] attrs = new Attribute[runtimeAttributes.Count + 1];
                   runtimeAttributes.CopyTo(attrs, 0);
                   attrs[runtimeAttributes.Count] = new BrowsableAttribute(false);
                   prop = TypeDescriptor.CreateProperty(this.GetType(), propname, prop.PropertyType, attrs);
                   properties[propname] = prop;
              }
         }
    
         return properties;
    }
    
     
    I don't feel as though the above causes adverse side-effects causing the situation that I'm having, but perhaps (hopefully) I am wrong.
     
    Any help is appreciated.
     
    Thanks


    • Edited by Jace Brewster Wednesday, May 4, 2011 5:11 PM for Clarity
    Wednesday, May 4, 2011 5:09 PM

All replies

  • Well, I don't see why you want to serialize a property that cannot be changed in design-time using the property grid.  If it is not editable, its value cannot change and therefore you shouldn't serialize it in the first place because it should have the default value.  Or am I wrong?
    MCP
    Wednesday, May 4, 2011 5:21 PM
  • it seems logical to me that if a property is not browsable, it is not serialized. Design time serialization is for what you do at DESIGN time, and if it's not visible at design time, what would be the purpose of saving it? or is that not what you're saying?
    Regards, Nico
    Wednesday, May 4, 2011 5:30 PM
  • Perhaps the designer agrees with you, and that's what causes the situation, however (going into more detail of the scenario):

     

    I have a ToolBox implementation of IToolBoxService. Like in VS, I am dragging controls from it to the design surface. I'm wishing to make use of the Control.Tag property to persist other information about the control when it is dropped onto the surface. (The ToolBoxItem holds an object of information, that when the control is dropped, it sets the <Control>.Tag equal to this same object of information.) So in effect, the property is changed during design-time, although only once, when the control is created on the surface.

    Wednesday, May 4, 2011 5:31 PM
  • I see.  I don't agree with the approach, though.  What if I wanted to use Tag for something else?  I think you need a property extender that adds a new property to every control in the form.
    MCP
    Wednesday, May 4, 2011 5:34 PM
  •  

     I agree the approach may not be the cleanest, but it's all that I've come up with so far - I'm attempting to re-factor from a different implementation.

     This design surface implementation is for a very specific purpose. The end result is intended to be a simplified form creation tool, that will require no coding to be involved to complete the form, but with a limited set of pre-defined logic/rules. In this case if there were something else that would be intended to associate with the controls, it would be added to the object that is tagged to begin with; so the use of the Tag property is just convenient (or so I'm thinking).

    The implementation I'm trying to get away from is extending the types of controls used (i.e. TextBox, CheckBox, etc) and including the information of the Tagged object as properties of the extended controls. These properties of course go all the way to serialization and back just fine, but anywhere that the created form will be used would need to be aware that the controls on the form are extensions of TextBox, or CheckBox. Granted, this is easy to do -

    if(ctrl is CheckBox)
    
    {
    	CheckBox chk = ctrl as CheckBox;
    
    ...
    
    }
    

    - but refactoring everywhere where this is checked, is not desirable, thus, the attempt of the above implementation is desirable - if it can work.

     

     


    • Edited by Jace Brewster Wednesday, May 4, 2011 5:57 PM for Format
    Wednesday, May 4, 2011 5:56 PM