Controls in visual studio provide lot of design time features such as drag-drop, specifying the properties using Property window. All these not only speed up the development process, but also reduce the amount of the code you need to type in, which otherwise give a scope to errors. Most of the time, the default behaviour of controls (web controls or normal windows controls) is sufficient to work with. But sometimes we do require extra functionality to be added each control at design time. To provide an example, customize text box control to have a property named
MyCustomName and allow the developer to specify this value at design time or run time. So the normal way to achieve this is deriving your own control from the text box and providing a public property to it.
Coming to the main problem, what if the property needs to be applied to all controls (label, button, checkbox etc..)? For an example,
CSSClass is a property that applies to most of the web controls. To provide such a property to all the controls, you need to derive a class for each control and have that extra property. In case you want to extend all these controls with one more property, the only way in this case is to touch all these classes. Alternative solution to this problem is a Provider.
A Provider is a control or component that lets you extend all or selected set of controls without creating extra classes. Tooltip, Help and Error Providers are the predefined providers. Tooltip provider, when dragged into the component tray, adds an extra property (ToolTip on toolTip1) to all the controls on the form. The runtime yields each control to the provider for the actual implementation of the extended properties. In doing so, the extender control gets a reference to the extendee and can check the type and name to read and update the state. You can read more on these providers at http://msdn.microsoft.com/msdnmag/issues/03/11/CuttingEdge/default.aspx.
In this article, the implementation of providers is explained using a problem at hand, and solving the same. To briefly describe the problem, the
CSSClass property for any web control in the ASP.NET web project indicates the style that can be applied to the control. To specify a value for this property, developer needs to open the CSS file, copy the respective CSS Class and paste it in the property window of the control. It would be really nice to have a list popping up in the property window showing all classes supported in the specified CSS file and show their configuration. Such that the developer can choose one from the list.
Since CSSClass is a property applies to all web controls, we are going to write a provider which gives a way to add this functionality. You can download the code using the link above. It contains the provider and a sample project to test the same. To create a provider, we need to implement
System.ComponentModel). This interface defines only one method
CanExtend which returns true based on the control.
public interface IExtenderProvider
bool CanExtend(object extendee);
In our example, we create a provider named
CSSNameProvider deriving from Component, such that when dragged, it will be put in the component tray. You can also derive it from Control, but it cannot be dropped into component tray.
public class CSSNameProvider : Component, IExtenderProvider
public bool CanExtend(object extendee)
return (extendee is WebControl);
Now you need to adorn
CSSNameProvider with an attribute called ProvideProperty. It takes in name of the property and type of the control to which this property appears in property window. We also need to create a public Get/Set property named
MyCSSName (not as CSSClass because every control already has this property). Now build your provider, open up your web project and add it to the tool box (Tool -> Add/Remove tool box items -> browse to select the
CSSNameProvider.dll). Drag the provider onto form. You can open up any web control property window and find a new property
MyCSSName on cssNameProvider1.
Once a value is set for
MYCSSName property, we are going to update CSSClass property of that control. Visual studio calls GetXXX(control) and SetXXX(control,string) methods when you get/set the property in extendee control.
GetMyCSSname method just returns the value of CSSName property.
[Description("Gets or Sets the CSS Class for the control.")]
public string GetMyCSSName(System.Web.UI.Control control)
Setting Browsable attribute to true indicates VS to show the property in property window. Now the actual solution to the problem starts. We need to show a list of CSS Classes from the file specified.
CSSNameProvider class also has a public property named
CSSFile. You can choose a file by clicking on ellipsis icon in provider properties window. As we are showing the File Dialog on click of ellipsis, we need to show an interface with all CSS Classes when you want to specify a value for
MyCSSName property. You achieve it by creating a
UITypeEditor. You need to derive a class from
System.Drawing.Design) which requires you to override
GetEditStyle indicates whether to show a combo (
UITypeEditorEditStyle.DropDown) or modal (
UITypeEditorEditStyle.Modal) window in the properties.
EditValue method is called when you click on combo icon or ellipsis icon. You can write in the code show your custom dialog boxes in this method.
You can use Editor attribute to associate a
UITypeEditor to a property. After putting down these
UITypeEditors, the provider lists a UI with all CSS Classes from which you can select the required one.
Providers are easy to implement and maintain. They provide a very rich feature to extend the controls. You can see the test web project how this provider works and go thru the code to understand the internals. You can also use this provider for your web project development. You can implement similar design time features that help the developer junta.
CSSNameProvider project contains CSSNameProvider.cs (implementation of the provider), DesignerClasses.cs (contains all UITypeEditors) and CSSClassViewer.cs (a form to list the CSS classes).
CSSClassTester is a web project containing a cssNameProvider object.