Hiding a non-virtual property for a derived control at design-time
I've recently been developing a custom control (BarControl
) that derived from an existing control (FooControl
). There were two requirements related to the derived control's border style:
- The
BorderStyle
property should not be modified at runtime - The
BorderStyle
property should not be displayed in the Properties pane at design-time
Since the base control exposed a BorderStyle
property, I thought I'd need to do three things:
- override the property
- change it's access modifier to
protected
so that only derived classes can access it - add a
[Browsable(false)]
attribute to remove it from Visual Studio's Properties pane
So I blithely whipped out the following code:
[Browsable(false)]
protected override BorderStyle BorderStyle
{
get { return base.BorderStyle; }
set { base.BorderStyle = value; }
}
The compiler just as blithely hit me with the following error:
Error 1 'BarControl.BorderStyle.get': cannot override inherited member 'FooControl.BorderStyle.get' because it is not marked virtual, abstract, or override
Error 2 'BarControl.BorderStyle.set': cannot override inherited member 'FooControl.BorderStyle.set' because it is not marked virtual, abstract, or override
Oops! I had expected the BorderStyle
property to be virtual and it wasn't. The solution--like most solutions--was obvious once I found it: use the new
, rather than the override
, modifier to hide the base class property. So I quickly changed the code to:
[Browsable(false)]
protected new BorderStyle BorderStyle
{
get { return base.BorderStyle; }
set { base.BorderStyle = value; }
}
Now the compiler was happy, so everything would work as expected, right? I switched to my test app, drug an instance of my control onto a form, and looked for the BorderStyle
property in the Properties pane. Lo and behold, it was still there. I was stumped. I had hidden the base property and marked the new property with [Browsable(false)]
. What could be wrong?
It took a close reading of the documentation for the new
modifier to find the problem: the new
modifier overrides members with the same signature. Since the access modifier is part of a member's signature, changing the access modifier from protected
to public
meant I wasn't hiding the BorderStyle
property in the base class. As a result, the BrowsableAttribute
was applied to the BorderStyle
property in the derived class but not the BorderStyle
property in the base class.
What to do. I needed to hide the BorderStyle
property at design time, so I needed to make it public
in the derived class; however, I also needed to hide the property at runtime so I needed to make it protected
. Perhaps, I could apply the protected
access modifier to the property's getter and setter methods while still leaving the property access modifier as public
. So I tried this:
[Browsable(false)]
public new BorderStyle BorderStyle
{
protected get { return base.BorderStyle; }
protected set { base.BorderStyle = value; }
}
The compiler didn't like it:
Error 1 Cannot specify accessibility modifiers for both accessors of the property or indexer 'BarControl.BorderStyle'
Since the goal was to keep the property from being modified at runtime, I settled on the following solution:
[Browsable(false)]
public new BorderStyle BorderStyle
{
get { return base.BorderStyle; }
protected set { base.BorderStyle = value; }
}
I'm not sure that there isn't a better solution, but this meets the criteria:
- The
BorderStyle
property is not displayed in the Properties pane at design-time - The
BorderStyle
property cannot be modified at runtime
So the three things I actually needed to do were
- hide the property in the base class with the
new
modifier - change the access modifier of the property's setter method to
protected
so that only derived classes can access it - add a
[Browsable(false)]
attribute to the derived class property to remove it from Visual Studio's Properties pane
I hope you find this helpful.
Cheers
Dan
Disclaimer: This posting is provided "AS IS" with no warranties, and confers no rights.