RadControls version |
Q2 2010
|
.NET version |
Any
|
Visual Studio version |
Any
|
programming language |
VB.NET
|
PROJECT DESCRIPTION
Many times when building custom user controls based on other controls, We would find it useful to be able to take advantage of Smart Tags to speed up the development process. This brief code library article explains how to add your own Smart Tags to a RadGridView (though the same principal can be used on many types of RadControl)
In this example, we have a requirement to build a custom user control that is inherited from a RadGridView. We are going to add our own properties to it that determine if a specific context menu will be visible and enabled, and then be able to set the defaults of this via the Smart Tags.
We will also ensure that we can still set the datasource and datamember of the RadGridView and still reach the Telerik Property Builder.
Step 1:
Define a new class that inherits from RadGridView.
In this step we will also set up the properties for the Context Menu Enabled and Context Menu Visible. We will also handle the ContextMenuOpening Event and show the context menu based on the properties, and create an event handler for when the user clicks on the context menu.
Public
Class
RadGridViewSmartTags
Inherits
Telerik.WinControls.UI.RadGridView
Private
m_MyContextMenuEnabled
As
Boolean
Private
m_MyContextMenuVisible
As
Boolean
=
True
<Category(
"Context Menus"
)> _
<Browsable(
True
)> _
<Description(
"Occurs when the sample context menu item is clicked"
)> _
Public
Event
SampleContextMenu_Clicked
As
EventHandler(Of EventArgs)
#Region "Constructor"
''' <summary>Initializes a new instance of the GridView class.</summary>
''' <remarks></remarks>
Public
Sub
New
()
Me
.ThemeClassName =
"Telerik.WinControls.UI.RadGridView"
End
Sub
#End Region
#Region " Public Properties "
#Region "ThemeName"
''' <summary>Theme Name</summary>
''' <value>The name of the theme</value>
''' <returns>Theme name as string</returns>
''' <remarks>Ensures the Theme name cannot be changed in the designer</remarks>
<[
ReadOnly
](
True
)> _
Public
Overloads
ReadOnly
Property
ThemeName()
As
String
Get
Return
MyBase
.ThemeName
End
Get
End
Property
#End Region
#Region "MyContextMenuEnabled"
<Browsable(
True
)> _
<Category(
"Context Menus"
)> _
Public
Overloads
Property
MyContextMenuEnabled()
As
Boolean
Get
Return
m_MyContextMenuEnabled
End
Get
Set
(
ByVal
value
As
Boolean
)
m_MyContextMenuEnabled = value
End
Set
End
Property
#End Region
#Region "MyContextMenuVisible"
<Browsable(
True
)> _
<Category(
"Context Menus"
)> _
Public
Overloads
Property
MyContextMenuVisible()
As
Boolean
Get
Return
m_MyContextMenuVisible
End
Get
Set
(
ByVal
value
As
Boolean
)
m_MyContextMenuVisible = value
End
Set
End
Property
#End Region
#End Region
#Region "GridView_ContextMenuOpening"
''' <summary>Grid View Context Menu Opening Event Handler.</summary>
''' <param name="sender">The event source</param>
''' <param name="e">The event arguments.</param>
''' <remarks></remarks>
Private
Sub
GridView_ContextMenuOpening(
ByVal
sender
As
System.
Object
, _
ByVal
e
As
ContextMenuOpeningEventArgs)
Handles
MyBase
.ContextMenuOpening
' if this is not the filter menu
If
TypeOf
e.ContextMenuProvider
Is
Telerik.WinControls.UI.GridDataCellElement _
AndAlso
Me
.SelectedRows.Count > 0
Then
If
m_MyContextMenuVisible
Then
Dim
contextMenuItemSample
As
New
RadMenuItem()
With
contextMenuItemSample
.Text =
"My Sample Context Menu"
.ToolTipText =
"Some tooltip"
.Enabled = m_MyContextMenuEnabled
End
With
e.ContextMenu.Items.Insert(0, contextMenuItemSample)
AddHandler
contextMenuItemSample.Click,
AddressOf
ContextMenuItemSample_Click
End
If
End
If
End
Sub
#End Region
#Region "ContextMenuItemSendToSample_Click"
''' <summary>Send to Branches Context Menu Item Click Event Handler.</summary>
''' <param name="sender">The event source.</param>
''' <param name="e">The event arguments.</param>
''' <remarks></remarks>
Private
Sub
ContextMenuItemSample_Click(
ByVal
sender
As
System.
Object
, _
ByVal
e
As
System.EventArgs)
RaiseEvent
SampleContextMenu_Clicked(
Me
,
New
EventArgs())
Me
.Focus()
End
Sub
#End Region
End
Class
Now we have a perfectly working RadGridView user control that we can use in our application. In terms of Smart Tags, the existing Smart Tags from the RadGridView are still there when you drag the control onto a new form. If some of those Smart Tags though are not needed in your development and you wanted to add some new ones, then we need to define a new class and make a couple of minor changes to our existing one.
So, let's say that the Smart Tags that we are really interested in keeping are:
* Setting the datasource and datamember
* Opening the Property Builder
* Choosing where to Dock the RadGridView.
We also want to be able to access our new properties for setting the Context Menu Visibility and Context Menu Enabled from our Smart Tags.
Step 2: We will define a new classes in the same file as the RadGridView user control (RadGridViewSmartTags)
First, import the following:
Now define new classes called RadGridViewSmartTagsControlDesigner and RadGridViewSmartTagsControlActionList
#Region "GridView Control Designer Class"
Public
Class
RadGridViewSmartTagsControlDesigner
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
RadGridViewSmartTagsControlActionList(
Me
.Component))
End
If
Return
lists
End
Get
End
Property
End
Class
#End Region
#Region "GridView Control Action List Class"
<ComplexBindingProperties(
"DataSource"
,
"DataMember"
)> _
Public
Class
RadGridViewSmartTagsControlActionList
Inherits
System.ComponentModel. _
Design.DesignerActionList
Private
m_GridView
As
RadGridViewSmartTags
''' <summary>Reference to DesignerActionUIService</summary>
''' <remarks></remarks>
Private
m_DesignerActionSvc
As
DesignerActionUIService
#Region "Constructor"
''' <summary>Initialises a new instance of the GridViewStandardControlActionList class.</summary>
''' <param name="component"></param>
''' <remarks></remarks>
Public
Sub
New
(
ByVal
component
As
IComponent)
MyBase
.
New
(component)
Me
.m_GridView =
DirectCast
(component, RadGridViewSmartTags)
Me
.m_DesignerActionSvc =
CType
(GetService(
GetType
(DesignerActionUIService)), DesignerActionUIService)
End
Sub
#End Region
#Region "GridView"
''' <summary>Gets or sets the GridView.</summary>
<CLSCompliant(
False
)> _
Public
Property
GridView()
As
RadGridViewSmartTags
Get
Return
m_GridView
End
Get
Set
(
ByVal
value
As
RadGridViewSmartTags)
m_GridView = value
End
Set
End
Property
#End Region
#Region "GetPropertyByName"
''' <summary></summary>
''' <param name="propName"></param>
''' <returns></returns>
''' <remarks></remarks>
Private
Function
GetPropertyByName(
ByVal
propName
As
String
)
As
PropertyDescriptor
Dim
prop
As
PropertyDescriptor
prop = TypeDescriptor.GetProperties(m_GridView)(propName)
If
prop
Is
Nothing
Then
Throw
New
ArgumentException(
"Invalid property."
, propName)
Else
Return
prop
End
If
End
Function
#End Region
#Region "Dock"
Public
Property
Dock()
As
System.Windows.Forms.DockStyle
Get
Return
m_GridView.Dock
End
Get
Set
(
ByVal
value
As
System.Windows.Forms.DockStyle)
GetPropertyByName(
"Dock"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "MyContextMenuEnabled"
Public
Property
MyContextMenuEnabled()
As
Boolean
Get
Return
m_GridView.MyContextMenuEnabled
End
Get
Set
(
ByVal
value
As
Boolean
)
GetPropertyByName(
"MyContextMenuEnabled"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "MyContextMenuVisible"
Public
Property
MyContextMenuVisible()
As
Boolean
Get
Return
m_GridView.MyContextMenuVisible
End
Get
Set
(
ByVal
value
As
Boolean
)
GetPropertyByName(
"MyContextMenuVisible"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "DataSource"
<RefreshProperties(RefreshProperties.Repaint)> _
<Editor(
"System.Windows.Forms.Design.DataSourceListEditor"
,
"System.Drawing.Design.UITypeEditor"
)> _
Public
Property
DataSource()
As
Object
Get
Return
m_GridView.DataSource
End
Get
Set
(
ByVal
value
As
Object
)
GetPropertyByName(
"DataSource"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "DataMember"
<Editor(
"System.Windows.Forms.Design.DataMemberListEditor"
,
"System.Drawing.Design.UITypeEditor"
)> _
Public
Property
DataMember()
As
String
Get
Return
m_GridView.DataMember
End
Get
Set
(
ByVal
value
As
String
)
GetPropertyByName(
"DataMember"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "get Sorted Action Items"
Public
Overrides
Function
GetSortedActionItems() _
As
DesignerActionItemCollection
Dim
items
As
New
DesignerActionItemCollection()
items.Add(
New
_
DesignerActionHeaderItem(
"Context Menu"
))
items.Add(
New
_
DesignerActionPropertyItem(
"MyContextMenuEnabled"
,
"My Menu Enabled"
,
"Context Menus"
,
"Determines if my context menu is enabled"
))
items.Add(
New
_
DesignerActionPropertyItem(
"MyContextMenuVisible"
,
"My Menu Visible"
,
"Context Menus"
,
"Determines if my context menu is visible"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Data"
))
items.Add(
New
_
DesignerActionPropertyItem(
"DataSource"
,
"Data Source"
,
"Data"
,
"Sets the data source"
))
items.Add(
New
_
DesignerActionPropertyItem(
"DataMember"
,
"Data Member"
,
"Data"
,
"Sets the data member"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Layout"
))
items.Add(
New
_
DesignerActionPropertyItem(
"Dock"
,
"Dock position"
,
"Layout"
,
"Determines the dock position"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Advanced"
))
items.Add(
New
_
DesignerActionMethodItem(
Me
,
"OnLaunchBuilder"
,
"Property Builder"
,
"Advanced"
,
"Launches the Telerik Property Builder"
,
False
))
Return
items
End
Function
#End Region
#Region "Launch Property Builder"
''' <summary>
''' This launches the property builder
''' </summary>
''' <remarks></remarks>
Public
Sub
OnLaunchBuilder()
Dim
service
As
IDesignerHost = TryCast(m_GridView.Site.GetService(
GetType
(IDesignerHost)), IDesignerHost)
Dim
transaction
As
DesignerTransaction = service.CreateTransaction(
String
.Format(CultureInfo.InvariantCulture,
"RadGridView{0}LaunchBuilderTransaction"
,
DirectCast
(m_GridView, RadGridView).Name))
Dim
propertyBuilder
As
New
Telerik.WinControls.UI.Design.RadGridViewPropertyBuilder(
DirectCast
(m_GridView, RadGridView))
Try
If
propertyBuilder.ShowDialog = DialogResult.OK
Then
transaction.Commit()
transaction =
Nothing
Dim
actionUIService
As
DesignerActionUIService = TryCast(m_GridView.Site.GetService(
GetType
(DesignerActionUIService)), DesignerActionUIService)
If
actionUIService IsNot
Nothing
Then
actionUIService.HideUI(m_GridView)
End
If
End
If
Finally
If
transaction IsNot
Nothing
Then
transaction.Cancel()
End
If
End
Try
End
Sub
#End Region
End
Class
#End Region
Note that there is a public property for each of the RadGridViewSmartTags properties that we want in our Smart Tags. This allows the Smart Tag to get to the grid in order to get and set the property.
We define the datasource and datamember properties with attributes to define the type of editor that will be used.
The GetSortedActionItems then adds in Header Items and Property Items into the Smart Tag UI. These can be grouped and named in any way you like.
The OnLaunchBuilder sub ensures that we can still reach the Property builder that Telerik has kindly given to us already.
Step 3: Lastly, we need to go back to the top and define an attribute on the RadGridViewSmartTag class to identify
So, our whole file should now look like this.
#Region "Imports"
Imports
System
Imports
System.ComponentModel
Imports
System.ComponentModel.Design
Imports
System.Diagnostics.CodeAnalysis
Imports
System.Globalization
Imports
System.Windows.Forms
Imports
Telerik.WinControls.Data
Imports
Telerik.WinControls
Imports
Telerik.WinControls.UI
#End Region
<Designer(
GetType
(RadGridViewSmartTagsControlDesigner))> _
Public
Class
RadGridViewSmartTags
Inherits
Telerik.WinControls.UI.RadGridView
Private
m_MyContextMenuEnabled
As
Boolean
Private
m_MyContextMenuVisible
As
Boolean
=
True
<Category(
"Context Menus"
)> _
<Browsable(
True
)> _
<Description(
"Occurs when the sample context menu item is clicked"
)> _
Public
Event
SampleContextMenu_Clicked
As
EventHandler(Of EventArgs)
#Region "Constructor"
''' <summary>Initializes a new instance of the GridView class.</summary>
''' <remarks></remarks>
Public
Sub
New
()
Me
.ThemeClassName =
"Telerik.WinControls.UI.RadGridView"
End
Sub
#End Region
#Region " Public Properties "
#Region "ThemeName"
''' <summary>Theme Name</summary>
''' <value>The name of the theme</value>
''' <returns>Theme name as string</returns>
''' <remarks>Ensures the Theme name cannot be changed in the designer</remarks>
<[
ReadOnly
](
True
)> _
Public
Overloads
ReadOnly
Property
ThemeName()
As
String
Get
Return
MyBase
.ThemeName
End
Get
End
Property
#End Region
#Region "MyContextMenuEnabled"
<Browsable(
True
)> _
<Category(
"Context Menus"
)> _
Public
Overloads
Property
MyContextMenuEnabled()
As
Boolean
Get
Return
m_MyContextMenuEnabled
End
Get
Set
(
ByVal
value
As
Boolean
)
m_MyContextMenuEnabled = value
End
Set
End
Property
#End Region
#Region "MyContextMenuVisible"
<Browsable(
True
)> _
<Category(
"Context Menus"
)> _
Public
Overloads
Property
MyContextMenuVisible()
As
Boolean
Get
Return
m_MyContextMenuVisible
End
Get
Set
(
ByVal
value
As
Boolean
)
m_MyContextMenuVisible = value
End
Set
End
Property
#End Region
#End Region
#Region "GridView_ContextMenuOpening"
''' <summary>Grid View Context Menu Opening Event Handler.</summary>
''' <param name="sender">The event source</param>
''' <param name="e">The event arguments.</param>
''' <remarks></remarks>
Private
Sub
GridView_ContextMenuOpening(
ByVal
sender
As
System.
Object
, _
ByVal
e
As
ContextMenuOpeningEventArgs)
Handles
MyBase
.ContextMenuOpening
' if this is not the filter menu
If
TypeOf
e.ContextMenuProvider
Is
Telerik.WinControls.UI.GridDataCellElement _
AndAlso
Me
.SelectedRows.Count > 0
Then
If
m_MyContextMenuVisible
Then
Dim
contextMenuItemSample
As
New
RadMenuItem()
With
contextMenuItemSample
.Text =
"My Sample Context Menu"
.ToolTipText =
"Some tooltip"
.Enabled = m_MyContextMenuEnabled
End
With
e.ContextMenu.Items.Insert(0, contextMenuItemSample)
AddHandler
contextMenuItemSample.Click,
AddressOf
ContextMenuItemSample_Click
End
If
End
If
End
Sub
#End Region
#Region "ContextMenuItemSendToSample_Click"
''' <summary>Send to Branches Context Menu Item Click Event Handler.</summary>
''' <param name="sender">The event source.</param>
''' <param name="e">The event arguments.</param>
''' <remarks></remarks>
Private
Sub
ContextMenuItemSample_Click(
ByVal
sender
As
System.
Object
, _
ByVal
e
As
System.EventArgs)
RaiseEvent
SampleContextMenu_Clicked(
Me
,
New
EventArgs())
Me
.Focus()
End
Sub
#End Region
End
Class
#Region " Smart Tag "
#Region "GridView Control Designer Class"
Public
Class
RadGridViewSmartTagsControlDesigner
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
RadGridViewSmartTagsControlActionList(
Me
.Component))
End
If
Return
lists
End
Get
End
Property
End
Class
#End Region
#Region "GridView Control Action List Class"
<ComplexBindingProperties(
"DataSource"
,
"DataMember"
)> _
Public
Class
RadGridViewSmartTagsControlActionList
Inherits
System.ComponentModel. _
Design.DesignerActionList
Private
m_GridView
As
RadGridViewSmartTags
''' <summary>Reference to DesignerActionUIService</summary>
''' <remarks></remarks>
Private
m_DesignerActionSvc
As
DesignerActionUIService
#Region "Constructor"
''' <summary>Initialises a new instance of the GridViewStandardControlActionList class.</summary>
''' <param name="component"></param>
''' <remarks></remarks>
Public
Sub
New
(
ByVal
component
As
IComponent)
MyBase
.
New
(component)
Me
.m_GridView =
DirectCast
(component, RadGridViewSmartTags)
Me
.m_DesignerActionSvc =
CType
(GetService(
GetType
(DesignerActionUIService)), DesignerActionUIService)
End
Sub
#End Region
#Region "GridView"
''' <summary>Gets or sets the GridView.</summary>
<CLSCompliant(
False
)> _
Public
Property
GridView()
As
RadGridViewSmartTags
Get
Return
m_GridView
End
Get
Set
(
ByVal
value
As
RadGridViewSmartTags)
m_GridView = value
End
Set
End
Property
#End Region
#Region "GetPropertyByName"
''' <summary></summary>
''' <param name="propName"></param>
''' <returns></returns>
''' <remarks></remarks>
Private
Function
GetPropertyByName(
ByVal
propName
As
String
)
As
PropertyDescriptor
Dim
prop
As
PropertyDescriptor
prop = TypeDescriptor.GetProperties(m_GridView)(propName)
If
prop
Is
Nothing
Then
Throw
New
ArgumentException(
"Invalid property."
, propName)
Else
Return
prop
End
If
End
Function
#End Region
#Region "Dock"
Public
Property
Dock()
As
System.Windows.Forms.DockStyle
Get
Return
m_GridView.Dock
End
Get
Set
(
ByVal
value
As
System.Windows.Forms.DockStyle)
GetPropertyByName(
"Dock"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "MyContextMenuEnabled"
Public
Property
MyContextMenuEnabled()
As
Boolean
Get
Return
m_GridView.MyContextMenuEnabled
End
Get
Set
(
ByVal
value
As
Boolean
)
GetPropertyByName(
"MyContextMenuEnabled"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "MyContextMenuVisible"
Public
Property
MyContextMenuVisible()
As
Boolean
Get
Return
m_GridView.MyContextMenuVisible
End
Get
Set
(
ByVal
value
As
Boolean
)
GetPropertyByName(
"MyContextMenuVisible"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "DataSource"
<RefreshProperties(RefreshProperties.Repaint)> _
<Editor(
"System.Windows.Forms.Design.DataSourceListEditor"
,
"System.Drawing.Design.UITypeEditor"
)> _
Public
Property
DataSource()
As
Object
Get
Return
m_GridView.DataSource
End
Get
Set
(
ByVal
value
As
Object
)
GetPropertyByName(
"DataSource"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "DataMember"
<Editor(
"System.Windows.Forms.Design.DataMemberListEditor"
,
"System.Drawing.Design.UITypeEditor"
)> _
Public
Property
DataMember()
As
String
Get
Return
m_GridView.DataMember
End
Get
Set
(
ByVal
value
As
String
)
GetPropertyByName(
"DataMember"
).SetValue(m_GridView, value)
End
Set
End
Property
#End Region
#Region "get Sorted Action Items"
Public
Overrides
Function
GetSortedActionItems() _
As
DesignerActionItemCollection
Dim
items
As
New
DesignerActionItemCollection()
items.Add(
New
_
DesignerActionHeaderItem(
"Context Menu"
))
items.Add(
New
_
DesignerActionPropertyItem(
"MyContextMenuEnabled"
,
"My Menu Enabled"
,
"Context Menus"
,
"Determines if my context menu is enabled"
))
items.Add(
New
_
DesignerActionPropertyItem(
"MyContextMenuVisible"
,
"My Menu Visible"
,
"Context Menus"
,
"Determines if my context menu is visible"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Data"
))
items.Add(
New
_
DesignerActionPropertyItem(
"DataSource"
,
"Data Source"
,
"Data"
,
"Sets the data source"
))
items.Add(
New
_
DesignerActionPropertyItem(
"DataMember"
,
"Data Member"
,
"Data"
,
"Sets the data member"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Layout"
))
items.Add(
New
_
DesignerActionPropertyItem(
"Dock"
,
"Dock position"
,
"Layout"
,
"Determines the dock position"
))
items.Add(
New
_
DesignerActionHeaderItem(
"Advanced"
))
items.Add(
New
_
DesignerActionMethodItem(
Me
,
"OnLaunchBuilder"
,
"Property Builder"
,
"Advanced"
,
"Launches the Telerik Property Builder"
,
False
))
Return
items
End
Function
#End Region
#Region "Launch Property Builder"
''' <summary>
''' This launches the property builder
''' </summary>
''' <remarks></remarks>
Public
Sub
OnLaunchBuilder()
Dim
service
As
IDesignerHost = TryCast(m_GridView.Site.GetService(
GetType
(IDesignerHost)), IDesignerHost)
Dim
transaction
As
DesignerTransaction = service.CreateTransaction(
String
.Format(CultureInfo.InvariantCulture,
"RadGridView{0}LaunchBuilderTransaction"
,
DirectCast
(m_GridView, RadGridView).Name))
Dim
propertyBuilder
As
New
Telerik.WinControls.UI.Design.RadGridViewPropertyBuilder(
DirectCast
(m_GridView, RadGridView))
Try
If
propertyBuilder.ShowDialog = DialogResult.OK
Then
transaction.Commit()
transaction =
Nothing
Dim
actionUIService
As
DesignerActionUIService = TryCast(m_GridView.Site.GetService(
GetType
(DesignerActionUIService)), DesignerActionUIService)
If
actionUIService IsNot
Nothing
Then
actionUIService.HideUI(m_GridView)
End
If
End
If
Finally
If
transaction IsNot
Nothing
Then
transaction.Cancel()
End
If
End
Try
End
Sub
#End Region
End
Class
#End Region
#End Region
The screenshot attached shows the result.
Richard