| Author: |
Carlos J. Quintero (Microsoft MVP) |
Applies to: |
Microsoft Visual Studio .NET 2002 |
| Date: |
April 2005 |
|
Microsoft Visual Studio .NET 2003 |
| Updated: |
March 2013 |
|
Microsoft Visual Studio 2005 |
| |
|
|
Microsoft Visual Studio 2008 |
| |
|
|
Microsoft Visual Studio 2010 |
| |
|
|
Microsoft Visual Studio 2012 |
Introduction
This article describes how to manipulate a Windows form and its controls (either selected or not) from a Visual Studio .NET add-in.
More Information
The following VB.NET sample shows you how to enumerate and manipulate the
controls of a Windows Form or Usercontrol. When loaded, the add-in gets the
active designer window, shows the count of selected controls (using the
ISelectionService interface) and changes the Tag property of each control of the
form.
Private m_objDTE As EnvDTE.DTE
Public Sub OnConnection(ByVal application As Object, _
ByVal connectMode As Extensibility.ext_ConnectMode, _
ByVal addInInst As Object, ByRef custom As System.Array) _
Implements Extensibility.IDTExtensibility2.OnConnection
' Note:
' - Add the following references to the project:
' System.Windows.Forms
' - Add the following Imports to this file:
' Imports System.ComponentModel
' Imports System.ComponentModel.Design
' Imports System.Windows.Forms
Dim objWindow As Window
Dim objIDesignerHost As IDesignerHost
Dim objIComponent As IComponent
Dim colPropertyDescriptorCollection As PropertyDescriptorCollection
Dim objPropertyDescriptor As PropertyDescriptor
Dim objIContainer As IContainer
Dim objIServiceProvider As IServiceProvider
Dim objISelectionService As ISelectionService
Try
m_objDTE = DirectCast(application, EnvDTE.DTE)
If connectMode = ext_ConnectMode.ext_cm_AfterStartup Then
' Get the active window
' Note: ensure that a Design window is active before running this code
' Note also that there is a bug in Visual Studio .NET
and the ActiveWindow property
' returns the first window of the document that was open, which could be
' the code window, and not the active window as it would be expected.
objWindow = m_objDTE.ActiveDocument.ActiveWindow
' Get the designer host
objIDesignerHost = DirectCast(objWindow.Object, IDesignerHost)
' Get the service provider
objIServiceProvider = DirectCast(objIDesignerHost, IServiceProvider)
' Get the selection service
objISelectionService = DirectCast(objIServiceProvider.GetService( _
GetType(ISelectionService)), ISelectionService)
' Show the count of selected controls
MessageBox.Show("The active designer has " & _
objISelectionService.SelectionCount.ToString() & " control(s) selected.")
' Get the container
objIContainer = objIDesignerHost.Container
' Iterate the components in a linear way (not hierarchically)
For Each objIComponent In objIContainer.Components
If TypeOf objIComponent Is Form Then
' This component is the form itself. You could cast it to a Form object
' and use its Controls collection to iterate the controls in a hierarchical way
' Skip it for the purpose of this sample.
ElseIf TypeOf objIComponent Is UserControl Then
' Same previous comment, for the case of UserControls
Else ' It is a control of the form, or a component of the component tray
colPropertyDescriptorCollection = TypeDescriptor.GetProperties(objIComponent)
objPropertyDescriptor = colPropertyDescriptorCollection.Item("Tag")
If Not (objPropertyDescriptor Is Nothing) Then
objPropertyDescriptor.SetValue(objIComponent, "Tag modified")
End If
End If
Next
End If
Catch objException As Exception
MessageBox.Show(objException.ToString)
End Try
End Sub
Remarks
- This technique only works with Windows forms or usercontrols, not for Web
forms or usercontrols.
- There are other services that can be retrieved using the IServiceProvider. For
example, the IEventBindingService, used to set or get the event handlers of
controls.
- In order to persist the changes of a property value, you should use a PropertyDescriptor as shown in the code instead of casting the component to the
specific control and manipulating its properties directly.
- There are 3 kind of items that can be returned by the Components collection of
the container: components of the component tray of the form (for example, an ImageList control, which is not part of the form), the form and the controls of
the form.
- The Components collection of the container returns all the components and
controls in a linear fashion. If you want to get them in a hierarchical fashion,
you should get first the root component (IDesignerHost.RootComponent), cast it
to a Windows Form or UserControl, and then use its Controls collection
recursively.
Go back to the 'Resources for Visual Studio .NET extensibility' section for more articles like this
|