f you have used Visual Studio 2005, chances are you’ve noticed the new Smart Tag feature. Basically, a Smart Tag is a panel that is displayed next to a control, containing a list of commonly used properties. By saving you a trip to the Properties window for some of the more common properties you need to set, Smart Tag can improve development productivity.
Figure 1 shows the ListView control with its Smart Tag panel displayed. You display the Smart Tag by clicking on the small arrow icon known as the anchor.
The Smart Tag contains a list of actions or properties (such as View). Actions are items such as Edit Items, which will bring up another window for you to edit the items in the ListView control.
Most controls (be they Windows or Web Server controls) support Smart Tag. While use of Smart Tag is a great way to increase productivity, if you are a custom control developer Smart Tag can also serve you well. You can allow the users of your controls to utilize the Smart Tag feature of Visual Studio 2005.
In this article I will show you how you can add Smart Tag support to your custom control. For simplicity, I will create a custom Button control based on the standard Button control. Figure 2 shows the Smart Tag that you will create in this article.
Before you start building a custom control and its corresponding Smart Tag, it is useful to define some terms pertinent to Smart Tags (see Figure 3). Each item in the Smart Tag is known as the Designer Action Item. You can organize the various designer action items into categories known as Designer Action Headers. The list of items and headers in the Smart Tag is known as the Designer Action List.
Creating the Project
Using Visual Studio 2005, create a new Windows application. Name the application as C:SmartTag. All the necessary classes required to build Smart Tag are located in the System.ComponentModel.Design namespace, which is stored in the System.Design.dll assembly. So, you need to add a reference to the System.Design.dll assembly in the project (see Figure 4).
|Figure 3. Knowing the Jargon: You’ll need to identify some key terms to work effectively with the Smart Tag.|
Creating the Component
To create a custom control, add a new Class template to the project and use the default name of Class1.vb. To keep things simple, I am going to simply create a custom Button control that inherits from the standard Button control. And so, in Class1.vb, add the following:
Public Class MyButton Inherits System.Windows.Forms.ButtonEnd Class
Note that you can enhance the MyButton control by adding properties and methods. You can also override some of its existing methods and properties.
Creating the Control Designer
The next step is to create the control designer (Smart Tag) for your custom control.
First, add the following namespace at the top of Class1.vb:
Imports System.ComponentModelImports System.ComponentModel.Design
Add the following MyButtonDesigner class to Class1.vb:
Public Class MyButtonDesigner Inherits System.Windows.Forms.Design.ControlDesigner Private lists As DesignerActionListCollection Public Overrides ReadOnly Property ActionLists() _ As DesignerActionListCollection Get If lists Is Nothing Then lists = New _ DesignerActionListCollection() lists.Add( _ New MyButtonActionList(Me.Component)) End If Return lists End Get End PropertyEnd Class
|Figure 4. Adding a Reference: Add the System.Design.dll assembly to the project.|
You use the ControlDesigner class for extending the design mode behavior of a Windows control. In this case, you want to display a Smart Tag for the custom control. The MyButtonDesigner class contains a private member variable called lists that contains the Designer Action List. The purpose of this variable is to contain a list of Designer Action Items. This is done by creating an instance of the MyButtonActionList class (which I will define in the next section).
To associate the custom control with the control designer, you need to add the
_Public Class MyButton Inherits System.Windows.Forms.ButtonEnd Class
Creating the Designer Action List
The MyButtonActionList class will create the list of designer action items available in the Smart Tag. Add the MyButtonActionList class to Class1.vb.
Public Class MyButtonActionListInherits _ System.ComponentModel.Design.DesignerActionListEnd Class
First, declare the following private member variables:
'---reference to the custom control Private myOwnButton As MyButton '---reference to DesignerActionUIServicePrivate designerActionSvc As _ DesignerActionUIService = Nothing
Then create the constructor for the class. The constructor accepts a single argument, which is a reference to the custom control.
Public Sub New(ByVal component As IComponent) MyBase.New(component) Me.myOwnButton = component Me.designerActionSvc = _ CType(GetService(GetType( _ DesignerActionUIService)), _ DesignerActionUIService) End Sub
Next, add a function named GetPropertyByName() to retrieve the various properties of the custom control. I will explain the importance of using this function later on in this article.
Private Function GetPropertyByName( _ ByVal propName As String) _ As PropertyDescriptor Dim prop As PropertyDescriptor prop = _ TypeDescriptor.GetProperties( _ myOwnButton)(propName) If prop Is Nothing Then Throw New ArgumentException( _ "Invalid property.", propName) Else Return prop End If End Function
Next, declare the various action list items in the Smart Tag as properties. Figure 5 shows the various items in the Smart Tag and their corresponding properties; Listing 1 is the code.
Specifically, the GetSortedActionItems() method from Listing 2 will populate the Smart Tag with the list of designer action items and arrange them in the order that you specify within this method. Figure 6 shows the arguments for the Add() method of the DesignerActionItemCollection class.
Testing the Application
To test the application, first compile the application by going to Build->Built SmartTag. Then drag and drop the MyButton control from the Toolbox (under the SmartTag Components tab; see Figure 7) onto Form1.
Earlier, I mentioned the need to define the GetPropertyByName() function to retrieve the various properties of the custom control. This is because the properties of a custom control must be set through a proxy property (which, in this case, is returned by the GetPropertyByName() function). You might be tempted to set the property of a control directly, like this:
|Figure 9. No Change: Resist the urge to set the properties of the control directly. If you do, the Properties window will not reflect the changes you make.|
Public Property [Text]() As String Get Return myOwnButton.Text End Get Set(ByVal value As String) '---setting the property directly myOwnButton.Text = value End Set End Property
However, in that case, if you were to set, say, the “Text String” item in the Smart Tag to some string such as “OK,” the Properties window will not reflect the changes (see Figure 9). Therefore the properties must be set through a proxy.
In this article, you have seen how to create Smart Tags for your custom control. If you are a control developer, adding a Smart Tag will make your control more user-friendly and efficient.