Blue Theme Orange Theme Green Theme Red Theme
 
6 Months Free & No Setup Fees ASP.NET Hosting!
Home | Forums | ASP.NET 2.0 Tutorials | Web Services | How Do I...? | Class Browser | WPF Quick Starts | Advertise with Us
 | Consulting  
Submit an Article Submit a Blog 
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
Team Foundation Server Hosting
Search :       Advanced Search »
Home » Enterprise Development » Extending Your Working Environment in Visual Studio - Advanced

Extending Your Working Environment in Visual Studio - Advanced

In my previous article, you learned about how to create wizards and some simple objects such as DTE, Solutions, Project and Project Item. These objects help us to customize our Visual Studio working environment.

Page Views : 3107
Downloads : 22
Rating :
 Rate it
Level : Beginner
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
ExtndingWorkEnv2.zip
 
 
Nevron Gauge for SharePoint
Become a Sponsor
 Tag Cloud
 Latest Jobs
More ... 
 Latest Interview Questions
More ... 

In my previous article we learned about how create wizards and some simple objects such as DTE, Solution, Project and Project Item. These objects help us to customize our Visual Studio working environment.

In todays article, we will delve deeper into the object model. We will develop an explorer to browse different classes and interfaces and their methods in a project.

Knowing Automation Object Model

Before we start with development lets get familiar with classes we will be using.
We will be using some classes from System.Reflection namespace and many classes from EnvDte namespace. Lets start with EnvDTE namespace  

Object model in EnvDTE namespace is called as Visual Studio .net Automation Object Model. DTE stands for Development Tools Extensibility. 

DTE Object :
EnvDte namespace has one top-level object DTE. DTE implements interface called as _DTE. To get hold of any other object that represent any entity in Visual Studio.Net runtime environment, we must get hold of DTE object. To get instance of DTE, our class must implement IDTWizard interface and must implement the only method of this interface i.e. Execute method. Of the parameters of the method is DTE object.

Solution :
DTE object has a property that represents solution opened in the VS.Net runtime environment.

Projects :
Solution object has property named Projects that contains collection of all projects opened in that solution.

ProjectItems collection and ProjectItem :
Projects collection contains Project objects; one project object represents one project opened in VS.Net. Each project has property named ProjectItems. This property represents all the project items such as all the files in the project, folder, sub projects, etc. All the project items in each project are grouped together in ProjectItems collection.

Each project item is of one of the following kind

  • Misc
  • Physical File
  • Physical Folder
  • Sub Project

So the picture looks like  

Object model at this level looks simple and easy to understand. From now onwards it starts getting complicated.

FileCodeModel :
Each project item has FileCodeModel object. This is top level object to access programmatic constructs in a source file. Using this object you can add various code elements at source file level such as Namespace, class, Interface, Structures, etc.

FileCodeModel object contains CodeElement collection. This is a collection of various types of code constructs such as CodeClass, CodeInterface, CodeEnum, CodeVariable, CodeFunction, etc. These constructs help you develop code and write it at desired location in the source file.

CodeElement :
All these code constructs inherit from CodeElement. Few of the Code constructs contain property called as member such as CodeNamespace and CodeClass constructs. This property exposes members of the parent constructs e.g. CodeNamespace contains CodeClasses, CodeInterface, CodeDelegate, etc.

In overall DTE object model, Window object represents the window opened in the development environment. Whenever we open a project item with particular file path, the item is opened in a window and handle of that window is returned.

So with filling in the details of CodeElement, the model will look like 

Develop Sample to read object model in a project

Now that we are aware of various objects, lets start with developing a small sample.
We are building on top of code from the previous article. In previous article we studied Solution object, ProjectItems collection, ProjectItem object.

Lets add a tree view control to UI

For each project item selected we will add Namespaces, Classes and Interfaces in the same. Add following code in lstProjectItems_SelectedIndexChanged event to WizardSampleUI.cs file.

private void lstProjectItems_SelectedIndexChanged(object sender, System.EventArgs e)
{
trvCodeElements.Nodes.Clear();
foreach(Project prj in this.dte.Solution.Projects)
{
if(prj.Name == lstProjects.SelectedItem.ToString())
{
foreach(ProjectItem prjItem in prj.ProjectItems)
{
if(lstProjectItems.SelectedItem.ToString() == prjItem.Name)
{
LoadProjectItemdataInProjectItem(prjItem);
break;
}
}
}
}
}

The function LoadProjectItemdataInProjectItem will add all the items in the prjItem to treeview.
Add following function to WizardSampleUI.cs file.

/// <summary>
/// Displays the project item data for selected project.
/// </summary>
private void LoadProjectItemdataInProjectItem(ProjectItem prjItem)
{
switch(prjItem.Kind)
{
case EnvDTE.Constants.vsProjectItemKindMisc:
lblItemKindText.Text = "Misc";
break;
case EnvDTE.Constants.vsProjectItemKindPhysicalFile:
lblItemKindText.Text = "PhysicalFile";
if(prjItem.Name.EndsWith(".cs"))
loadProjectItemdata(prjItem);
break;
case EnvDTE.Constants.vsProjectItemKindPhysicalFolder:
lblItemKindText.Text = "PhysicalFolder";
break;
case EnvDTE.Constants.vsProjectItemKindSubProject:
lblItemKindText.Text = "SubProject" ;
break;
}
}

Here we called loadProjectItemData function. This function will add Namespaces, Classes and Interfaces within the code file to treeview. Note that we are calling this function only if the file project item is a code file.

Now add following code to WizardSampleUI.cs file.

/// <summary>
/// This function addes Namespaces, Classes and Interfaces of a project item to treeview.
/// </summary>
/// <param name="prjToLoad"></param>
private void loadProjectItemdata(ProjectItem prjToLoad)
{
prjToLoad.Open("{7651A701-06E5-11D1-8EBD-00A0C90F26EA}"); //Viewkind pertaining to type of view to use.
TreeNode rootNd = trvCodeElements.Nodes.Add(prjToLoad.Name);
TreeNode nsNodes = trvCodeElements.Nodes.Add("NameSpaces");
foreach(CodeElement cdElement in prjToLoad.FileCodeModel.CodeElements)
{
if(cdElement.Kind == vsCMElement.vsCMElementNamespace)
{
TreeNode ndNameSpace = nsNodes.Nodes.Add(cdElement.FullName);
ndNameSpace.Tag = cdElement; //Tag will later used to navigate to project item.
TreeNode ndClassNodes = ndNameSpace.Nodes.Add("Classes");
TreeNode ndInterfacesNodes = ndNameSpace.Nodes.Add("Interfaces");
foreach(CodeElement cdClassElmnt in ((CodeNamespace)cdElement).Members)
{
if(cdClassElmnt.Kind == vsCMElement.vsCMElementClass)
{
TreeNode classNode = ndClassNodes.Nodes.Add(cdClassElmnt.Name);
classNode.Tag = cdClassElmnt;//Tag will later used to navigate to project item.
loadClassMembers(classNode,(CodeClass)cdClassElmnt);
continue;
}
if(cdClassElmnt.Kind == vsCMElement.vsCMElementInterface)
{
TreeNode interfaceNode = ndInterfacesNodes.Nodes.Add(cdClassElmnt.Name);
interfaceNode.Tag = cdClassElmnt;//Tag will later used to navigate to project item.
loadInterfaceMembers(interfaceNode,(CodeInterface)cdClassElmnt);
continue;
}
//Same way you can add code for Delegates, Enums and Structs.
}
}
}
}

This is an important piece of code. There are couple of important methods and properties used in this function.

Notice the Open function being called on parameter prjToLoad and the parameter passed to this function. The parameter represents a GUID. This GUID represents the kind of view in which the window should be opened. The GUID we mentioned will open the project item as Code Window. Other views possible are

GUID View Type
{7651A701-06E5-11D1-8EBD-00A0C90F26EA} Code View
{7651A700-06E5-11D1-8EBD-00A0C90F26EA} Debugger View
{7651A702-06E5-11D1-8EBD-00A0C90F26EA} Designer View
{00000000-0000-0000-0000-000000000000} Default view for the item
{7651A703-06E5-11D1-8EBD-00A0C90F26EA} Text view

Also check the FileCodeModel property used on prjToLoad. We are using CodeElements collection on this object.

Inside the first for loop we are checking the type of code element. The type of any code element is checked using Kind property. This property is of type Enum vsCMElementClass. The Kind property of the code element is compared with this Enum. We are checking if the code element is a NameSpace declaration.

Unfortunately I could not find any element that will represent Using statements though the Enum - vsCMElementClass supports it.

Lets move ahead.

Once we confirm that the code element is a NameSpace we type cast it to CodeNamespace type and use its Member property to access all the classes and interfaces declared in Namespace. The Member property returns collection of all CodeElements.
While looping thro the namespace members, we check the Kind of each code element and populate tree view with details of the code element using helper functions. These helper functions are similar to loadProjectItemdata function.

Different helper functions are used to populate data about Class, functions in class and properties in the class.

We have Tag property of TreeNode to our benefit. This property can hold any object. We want to add functionality that enables user to select the function/ class/ interface and open it in the code view pane. User will select the node and double click on it.
So while adding any treenode object we are initializing the Tag property of the treenode to the code element it represents 

In loadProjectItemdata function we have added code

TreeNode ndNameSpace = nsNodes.Nodes.Add(cdElement.FullName);
ndNameSpace.Tag = cdElement; //Tag will later used to navigate to project item.
navigate to project item.

Now lets add the double click event for tree view as follows: 

private void trvCodeElements_DoubleClick(object sender, System.EventArgs e)
{
if(trvCodeElements.SelectedNode.Tag != null)
{
//Following code will navigate to selected node.
Window prjItemWindow = ((CodeElement)trvCodeElements.SelectedNode.Tag).ProjectItem.Open("{7651A701-06E5-11D1-8EBD-00A0C90F26EA}");
//Activate the code pane.
prjItemWindow.Activate();
//Navigate to selected node.
((CodeElement)trvCodeElements.SelectedNode.Tag).StartPoint.TryToShow(vsPaneShowHow.vsPaneShowTop,0);
//"Edit.GoToDefinition",((CodeElement)trvCodeElements.SelectedNode.Tag).FullName);
}
}

In this code notice the use of Window object. In this code snippet, we retrieve the code element selected by user using the Tag property of selected node. We type cast it to CodeElement. Each code element has a property ProjectItem. This property returns you the project item (code file/folder) it belongs to. We open this project item and obtain the Windows object by calling Open method on project item. Once we get the window, we activate the window by calling its Activate method. We want to show the code element user has selected in editor. Till now we have opened the project item that contains the code element user has selected.
Notice the use of StartPoint property of the code element. This property returns a TextPoint. Its similar to placing a cursor at a location in the editor. TextPoint is helps you navigate in the code window in the cursor style. We will see about TextPoint sometime later. The method TryToShow will bring up the code element selected by user in the editor.

When user double clicks on any function, parameter or class in the tree view.

dte.ExecuteCommand

This is very important and powerful method of DTE object. This method expects a command which is a menu operated command. E.g. to build the solution we go to Build menu and select Build Solution command. To execute the same command using dte.ExecuteCommand you will provide string parameter Build.BuildSolution. To get the list of all these commands, you can use command window.
e.g. In command window you can start typing Edit and you will get context sensitive help of all the commands available for Edit menu. In the same way you can find all the commands for main menus such as Build, Debug, Tools etc.

The other parameter for dte.ExecuteCommand is string of argument. This is optional and specific to each command.

What we achieved ?

We studied various objects of VS.Net automation object model.
We studied different properties and methods of these objects.
Using these objects we browsed through the code modules and projects.
We created an explorer that is similar to Class View explorer.
We were introduced to TextPoint object. This is an important object to navigate thro the text window and to manipulate the code.

The next step would be to generate code.

Comment Request!
Thank you for reading this post. Please post your feedback, question, or comments about this post Here.
Login to add your contents and source code to this article
 [Top] Rate this article
 
 About the author
 
raviraj_bh
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
ASP.NET 4 Hosting
Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites – Click Here!
 
 Post a Feedback, Comment, or Question about this article
Subject:
Comment:
Team Foundation Server Hosting
Become a Sponsor
 Comments
6 Months Free & No Setup Fees ASP.NET Hosting!
 © 2012  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.