
Introduction
This article provides a base class that helps developers build customized design-time extensions for components and controls through Smart Tag designer panels.
How to Use this Helper (Base) Class
You can easily define your custom Smart Tag panels containing your action list items (Properties, Methods (Verbs), and Texts). Here is a sample control which derives from the TextBox control and uses a custom designer (mySmartTagActionList). The items are added in the AddActionItems() method. Any property or method you want to add should be defined in your SmartTagActionList class which is derived from the SmartTagActionListBase class.
Here are the required steps to create your custom control designer:
- Define your control (or component) class (e.g.,
XTextBox)
- Define a
DesignerActionList class which inherits from SmartTagActionListBase. This part of the code should also be inserted to its body:
Public Class mySmartTagActionList1
Inherits SmartTagActionListBase
Private m_Control As XTextBox
Sub New(ByVal component As IComponent)
MyBase.New(component)
m_Control = CType(component, XTextBox)
End Sub
End Class
where XTextBox is the type (or class name) of your control. Here, the m_Control variable is used to cache a reference to the associated control of this designer for later uses.
You may also use Me.AutoShow = True in this constructor routine to auto-expand (auto-show) it whenever the user drags your control into the form.
Define the properties/methods you want (e.g., BackColor, ForeColor, and IsMultiline, in the below sample). Some properties are already defined in the base class (SmartTagActionListBase) such as: Name, Text, Font, RightToLeft.
Override the AddActionItems() method to add your Smart Tag panel items (ActionList items). You may use the AddActionProperty, AddActionMethod, AddActionHeader, and AddActionText methods to do this easily (see the sample code).
Add a Designer attribute to your control class like this:
<Designer(GetType(SmartTagControlDesigner(Of mySmartTagActionList)))>
where the mySmartTagActionList is the name of your SmartTagActionList class.
Note: if you want to define a designer for a component (not a control), just use SmartTagComponentDesigner instead of SmartTagControlDesigner:
<Designer(GetType(SmartTagComponentDesigner(Of mySmartTagActionList)))<
The Sample Code
Here is a sample control which uses a custom SmartTagPanel Designer:
Imports System.ComponentModel
<Designer(GetType(SmartTagControlDesigner(Of mySmartTagActionList)))> _
Public Class XTextBox
Inherits TextBox
End Class
Public Class mySmartTagActionList
Inherits SmartTagActionListBase
Private m_Control As XTextBox
Sub New(ByVal component As IComponent)
MyBase.New(component)
m_Control = CType(component, XTextBox)
End Sub
Public Property BackColor() As Color
Get
Return m_Control.BackColor
End Get
Set(ByVal value As Color)
Me.SetPropertyByName(m_Control, "BackColor", value)
End Set
End Property
Public Property ForeColor() As Color
Get
Return m_Control.ForeColor
End Get
Set(ByVal value As Color)
Me.SetPropertyByName(m_Control, "ForeColor", value)
End Set
End Property
Public Property IsMultiline() As Boolean
Get
Return m_Control.Multiline
End Get
Set(ByVal value As Boolean)
Me.SetPropertyByName(m_Control, "Multiline", value)
End Set
End Property
Public Sub SwapColors()
Dim c As Color = Me.ForeColor
Me.ForeColor = Me.BackColor
Me.BackColor = c
RefreshDesigner()
End Sub
Public Overrides Sub AddActionItems()
AddActionHeader("Main")
AddActionProperty("Name", "Name:", "Main", "")
AddActionProperty("Text", "Text:", "Main", "")
AddActionProperty("Font", "Font:", "Main", "")
AddActionProperty("IsMultiline", "Multiline:", "", "")
AddActionHeader("Colors")
AddActionProperty("ForeColor", "ForeColor:", _
"Colors", "Sets the ForeColor")
AddActionProperty("BackColor", "BackColor:", _
"Colors", "Sets the BackColor")
AddActionText("This is my info...", "Colors")
AddActionMethod("SwapColors", "Swap Colors", _
"Colors", "Swap ForeColor/BackColor", True)
End Sub
End Class
Notes
You may see this article: Creating Property Editors in Design Time for VS.NET Easily (UITypeEditor Helper), to create UITypeEditor's easily. An 'Editor' is related to a property, but a 'Designer' is related to a control or component (a class)! By means of UITypeEditors, you can provide a custom editor window (e.g., a dropdown window) to edit each property of a control. You may mix both of the 'Designer' and 'Editor' attributes to achieve better design-time extensions for components and controls.
| You must Sign In to use this message board. |
|
|
 |
|
 |
In the sample code, the SwapColors control has a line of code RefreshDesigner() - if I bring up the smart tag and click swap colors, then click off the control, then click back on the control and try to bring up the smart tag again, it crashes with "Object Reference not set to an instance of an object." It does not error if I remove RefreshDesigner, but of course the designer does not automatically swap the colors. Any ideas?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
If I pop up the smart tag on a control, and enter invalid information into a property, a message pops up. At first it looked like I could override the SetPropertyByName method because that is where an error is reported. But that is not the case. Is there a method to override so I can create my own error message box?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
First off all thanks a lot for this code, it’s very nice.
I have inherited from Panel and added some of my properties to its ‘Smart Tag’ which originally only contained dock in parent. All works fine here. But the ‘MoveSmartTag’, which easy moves around my panel, especially because even in design time I can toggle to deliberately click through my transparent control, is disappeared. I don’t know the proper name for ‘MoveSmartTag’, but it’s a ‘Smart Tag-like arrow box’ in the upper right corner to move around the control.
I would appreciate you’re help. Thanks in advance.
Best Regars, Magiel from Holland
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
I had the same problem, and I figured it out, so I'll share my discovery and solution. By default, a Panel uses a PanelDesigner which adds the "Move" icon as well as the "Dock In Parent" method. However, our SmartTagControlDesigner inherits from a basic ControlDesigner, which does not have those added items. Here is the inheritance: (I used the .NET Reflector tool)
PanelDesigner (adds panel-drawing (the little dotted line)) inherits from
ScrollableControlDesigner (adds scrolling functionality) inherits from
ParentControlDesigner (adds the Move icon and Dock in Parent) inherits from
ControlDesigner (only has basic functionality)
The best solution would be to change the code for SmartTagControlDesigner, and instead of inheriting from a ControlDesigner, inherit from a PanelDesigner. Surprisingly, however, this will not work, because the PanelDesigner is declared Friend and is not accessible. So the next best thing is to inherit from ScrollableControlDesigner(which is declared Public and is accessible). Inheriting from ScrollableControlDesigner will give you back everything the original "PanelDesigner" provides, except for the dotted-line border.
So, to sum up: Find this section of code:
Public Class SmartTagControlDesigner(Of DesignerActionList_Class As DesignerActionList) Inherits ControlDesigner
Replace it with this:
Public Class SmartTagControlDesigner(Of DesignerActionList_Class As DesignerActionList) Inherits ScrollableControlDesigner
(Nore: you might need to import or add a reference to System.Windows.Forms.Design and System.Design)
Finally, if you REALLY want to retain ALL the functionality of the original designer, you can do what I did and use the .NET Reflector tool to disassemble the original PanelDesigner, and copy and paste the code into your project. PanelDesigner:
Imports System.ComponentModel Imports System.ComponentModel.Design Imports System.Windows.Forms.Design Imports System.Drawing.Drawing2D
Public Class PanelDesigner Inherits ScrollableControlDesigner Public Sub New() MyBase.AutoResizeHandles = True End Sub Protected Overridable Sub DrawBorder(ByVal graphics As Graphics) Dim component As Panel = DirectCast(MyBase.Component, Panel) If ((Not component Is Nothing) AndAlso component.Visible) Then Dim borderPen As Pen = Me.BorderPen Dim clientRectangle As Rectangle = Me.Control.ClientRectangle clientRectangle.Width -= 1 clientRectangle.Height -= 1 graphics.DrawRectangle(borderPen, clientRectangle) borderPen.Dispose() End If End Sub Protected Overrides Sub OnPaintAdornments(ByVal pe As PaintEventArgs) Dim component As Panel = DirectCast(MyBase.Component, Panel) If (component.BorderStyle = BorderStyle.None) Then Me.DrawBorder(pe.Graphics) End If MyBase.OnPaintAdornments(pe) End Sub Protected ReadOnly Property BorderPen() As Pen Get Dim color As Color = IIf((Me.Control.BackColor.GetBrightness < 0.5), ControlPaint.Light(Me.Control.BackColor), ControlPaint.Dark(Me.Control.BackColor)) Dim pen As New Pen(color) pen.DashStyle = DashStyle.Dash Return pen End Get End Property
End Class
Then, change the SmartTagControlDesigner to:
Public Class SmartTagControlDesigner(Of DesignerActionList_Class As DesignerActionList) Inherits PanelDesigner
This is actually a good idea for anyone who is creating a custom control based on an existing control. For example, if you want to create a custom TabControl based on the existing one, you should use the .NET Reflector to disassemble the TabControlDesigner, then copy and paste it into your project, and then create another SmartTagControlDesigner that inherits TabControlDesigner.
I feel like I just wrote my own article! Sorry this reply was so lengthy!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | C#  sabrown100 | 11:53 18 Oct '07 |
|
|
 |
|
 |
Hi I am building a composite controls in which contains some custoemr web controls. Do I need to build the smartTag control is one or separte for each one?
Thanks.
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Hi, I am Kristipati Subramanyam, I created multicolumn ComboBox. Its working fine. I am trying to add design time support for my control. for this I searched in MSDN/CodeProject. Comparatively your solution is simple & easy for implemention. But, when I am trying to add smart tag using your solution, I am not able to get smart tag. Why? Please tell me, if there any special care we need to take care for adding smart tag to custom control inherited from ComboBox.
Kristipati
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Hi,
I follow your article and now I have my control with a smartTag just like I wanted, but now my control has an attribute(string) with a custom UITypeEditor (opens a form with grid navigation, select, ...). I wanna have that property on the smartTag but with the custom UITypeEditor like it show in the properties grid, not just the textbox.
How can I do this.
Thanks in advance, D
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
You can do this as well as you do it for properties of your control i.e. specify the Editor attribute for it. here is an example which use myEditor1 for a property named myProperty in the smart tag designer:
Public Class mySmartTagActionList1 Inherits SmartTagActionListBase
...
<EditorAttribute(GetType(myEditor1), _ GetType(System.Drawing.Design.UITypeEditor)) , DefaultValue("")> _ Public Property myProperty() As String ... End Property
...
Public Overrides Sub AddActionItems() ... AddActionProperty("myProperty", "myProperty:", "", "") End Sub
End Class
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
|
 |
|
 |
Nice article, it helped me a lot.
I would like to have a smartTike like the one in DataGridView, I mean auto-expand the panel as soon as the control is dropped onto the designer. how can I do this?
Help really appreciated
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You can do it simply by setting the AutoShow property to True in designer constructor. for example:
Public Class MyDesigner Inherits XControlDesignerActionList
Private myControl As XTextBox
Public Sub New(ByVal component As IComponent) MyBase.New(component) Me.AutoShow = Trueu '*** add this code '... End Sub ... End Class
-- modified at 10:14 Monday 22nd January, 2007
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|