Working with Project Items


Solutions manage a number of projects, and each project manages the files that are built into a program. Each project contains files that can be enumerated and programmed.

Enumerating Project Items

Files within a project are arranged hierarchically. A project can contain any number of files and one or more folders, which themselves can contain additional files and folders. To match this project hierarchy, the project object model is also arranged hierarchically, with the ProjectItems collection representing the nodes that contain items and the ProjectItem object representing each item within this collection. To enumerate this hierarchy, you use the ProjectItems and ProjectItem objects. The following macro walks the first level of the hierarchy of the ProjectItems and ProjectItem objects by using the Project.ProjectItems property to obtain the top-level ProjectItems object:

 Sub EnumTopLevelProjectItems()     Dim projItem As EnvDTE.ProjectItem     Dim projectProjectItems As EnvDTE.ProjectItems     Dim project As EnvDTE.Project          'Find the first project in a solution:     project = DTE.Solution.Projects.Item(1)     'Retrieve the collection of project items:     projectProjectItems = project.ProjectItems     'Walk the list of items in the collection:     For Each projItem In projectProjectItems         MsgBox(projItem.Name)     Next End Sub 

Some items within a project, such as a folder, are both an item within the project hierarchy and a container of other files and folders. Because these folders are both items and collections of items, a folder is represented in the project model hierarchy with both a ProjectItem object and a ProjectItems object. You can determine whether a ProjectItem node is also a container of more ProjectItem nodes by calling the ProjectItem.ProjectItems property, which returns a ProjectItems collection if the node can contain subitems. You can enumerate all the ProjectItem and ProjectItems objects within a project by writing a recursive macro function such as this:

 Sub EnumProjectItems(ByVal projItems As EnvDTE.ProjectItems)     Dim projItem As EnvDTE.ProjectItem     'Find all the ProjectItem objects in the given collection:     For Each projItem In projItems         MsgBox(projItem.Name)         'And walk any items the current item may contain:         EnumProjectItems(projItem.ProjectItems)     Next End Sub Sub EnumProject()     Dim project As EnvDTE.Project     'Find the first project in a solution:     project = DTE.Solution.Projects.Item(1)     EnumProjectItems(project.ProjectItems) End Sub 

The EnumProject macro first finds the ProjectItems collection of a given project, and then it calls the EnumProjectItems subroutine, which will find all the ProjectItem objects that the collection contains. If the ProjectItem object is itself a collection, it will recursively call the EnumProjectItems subroutine to display the items it contains.

Folders aren't the only items that can contain a collection of ProjectItem objects. Files such as Windows Forms and Web Forms are also collections of files. Each of these file types has associated resource files (in the form of .resx files), and they can also have an associated code-behind file. In the default state, Solution Explorer won't give any indication of whether these files are containers for other files, but you can modify it to show the files that these file types contain. Choose Show All Files from the Project menu to show all form files as expandable in the tree view that makes up Solution Explorer. When the EnumProject macro (shown earlier) is run, the ProjectItem.ProjectItems property returns a collection that contains the ProjectItem objects for these subitems. Code such as the EnumProject macro will return the same values whether or not the Show All Files menu command has been chosen. This command affects only the Solution Explorer user interface.

You can combine the techniques for enumerating files and files within folders to find a specific item within a project. Suppose you've created a Windows Forms application solution and modified the project to look like that shown in Figure 8-1.

image from book
Figure 8-1: A Windows Forms application with nested resources

Using the ProjectItem object and ProjectItems collection, you can write a macro such as the following to locate the Bitmap1.bmp file:

 Sub FindBitmap()     Dim project As EnvDTE.Project     Dim projectProjectItems As EnvDTE.ProjectItems     Dim resourcesProjectItem As EnvDTE.ProjectItem     Dim resourcesProjectItems As EnvDTE.ProjectItems     Dim bitmapsProjectItem As EnvDTE.ProjectItem     Dim bitmapsProjectItems As EnvDTE.ProjectItems     Dim bitmapProjectItem As EnvDTE.ProjectItem     'Get the project:     project = DTE.Solution.Item(1)     'Get the list of items in the project:     projectProjectItems = project.ProjectItems     'Get the item for the Resources folder:     resourcesProjectItem = projectProjectItems.Item("Resources")     'Get the collection of items in the Resources folder:     resourcesProjectItems = resourcesProjectItem.ProjectItems     'Get the item for the Bitmaps folder:     bitmapsProjectItem = resourcesProjectItems.Item("Bitmaps")     'Get the collection of items in the Bitmaps folder:     bitmapsProjectItems = bitmapsProjectItem.ProjectItems     'Get the item for the Bitmap1.bmp file:     bitmapProjectItem = bitmapsProjectItems.Item("Bitmap1.bmp")     MsgBox(bitmapProjectItem.Name) End Sub 

You can walk down the tree of the ProjectItem and ProjectItems hierarchy to find a specific file, but sometimes you might need a quicker and easier way of locating the ProjectItem object for a file with a specific file name in a project. You can use the FindProjectItem method of the Solution object to find an item by passing a portion of the file path to where the file is located on disk. For example, suppose two add-in projects have been created (using the Add-in Wizard) in a folder you created called Addins located in the root of drive C. Each of these two add-ins, MyAddin1 and MyAddin2, contains a file named Connect.cs. You could use the following macro to locate the Connect.cs file in either project:

 Sub FindItem()     Dim projectItem As EnvDTE.ProjectItem     projectItem = DTE.Solution.FindProjectItem("Connect.cs") End Sub 

However, because FindProjectItem returns any file that matches this file name, you can't tell which ProjectItem will be returned—the ProjectItem object for the Connect.cs in MyAddin1 or the ProjectItem object for Connect.cs in MyAddin2. To refine the search, you can supply a bit more of the file path as the specified file name, as shown in the following macro, which adds the name of the folder on disk that contains the MyAddin1 version of Connect.cs:

 Sub FindItemWithFolder()     Dim projectItem As EnvDTE.ProjectItem     projectItem = DTE.Solution.FindProjectItem("MyAddin1\Connect.cs") End Sub 

Of course, just as you can specify a portion of the path to find the ProjectItem, you can use the whole path to zero in on the exact item you want:

 Sub FindItemWithFullPath()     Dim projectItem As EnvDTE.ProjectItem     projectItem = _         DTE.Solution.FindProjectItem("C:\Addins\MyAddin1\Connect.cs") End Sub 

Adding and Removing Project Items

You can add new files to a project in two ways. The first way is to use the AddFromDirectory, AddFromFile, AddFromFileCopy, and AddFromTemplate methods of the ProjectItems interface (which we'll discuss shortly). The second way is to use the ItemOperations object. This object offers a number of file manipulation methods to help make working with files easier. The difference between using the methods of the ProjectItems object and the methods of ItemOperations is that the ProjectItems object gives an add-in or a macro more fine-grained control over where, within a project, the new file is created. The ItemOperations object methods are more user-interface oriented; they add the new file to the project or folder that is selected in Solution Explorer, or, if a file is selected, they add the item to the project or the folder containing that file. These features help make macro recording possible. If you start the macro recorder and then add a file into a project, a call to one of the methods of the ItemOperations object is recorded into the macro. The selected item is where files are added when the proper method is called.

One method of the ItemOperations object, AddExistingItem, takes as its only argument the path to a file on disk and adds this file to the selected project or folder within a project. Depending on the type of project, the file might be copied to the project folder before being added, or a reference might be added to the file without copying the file. Visual Basic and Visual C# projects are folder-based, which means that the project hierarchy shown in Solution Explorer is mirrored on disk, and any files within the project must be in the folder containing the project or in one of its subfolders. Microsoft Visual C++® projects work a little differently: a file that is part of the project can be located anywhere on disk, and it doesn't need to be within the folder containing the project or a child folder of that folder. For instance, suppose a file named file.txt is located in the root directory of the C drive. If we run the macro

 Sub AddExistingItem()     DTE.ItemOperations.AddExistingItem("C:\file.txt") End Sub 

and the item selected in Solution Explorer is a Visual C# or a Visual Basic project or one of its children, file.txt will be copied into the folder or subfolder containing the project file and then added to the project. But if the selected item is a Visual C++ project, the file will be left in place and a reference will be added to this file.

Whereas AddExistingItem inserts a file from disk into a project, AddNewItem creates a new file and adds it to the project. This method takes two arguments and has the following method signature:

 public EnvDTE.ProjectItem AddNewItem(string Item = "General\Text File",         string Name = "") 

You can add a new item through the user interface by right-clicking on a project and choosing Add | Add New Item from the shortcut menu, which brings up the Add New Item dialog box.

The Add New Item dialog box is related to the AddNewItem method in that the first parameter of AddNewItem is the type of file to be added. You can find this file type by using the Add New Item dialog box. Figure 8-2 shows two different Add New Item dialog boxes— the Add New Item dialog box for a Visual C# project (you will also see a similar dialog box for Visual Basic and Microsoft Visual J#® projects) and the dialog box you use when trying to add a new item to a Visual C++ project. If the dialog box you see is of the first type, the name is computed by first taking the language name, such as Visual C#, Visual Basic, or Visual J#, adding the string "Project Items\", and appending the name of the file selected within the list view on the right side of the dialog box. This means that the string to add a class file to a Visual C# project would be "Visual C# Project Items\Class." If the dialog that appears looks like that in the second Add New Item dialog box in Figure 8-2, the file type is calculated by taking the path to the item selected in the tree view, with each portion of the path separated by a backslash, and then adding the title of the item in the list on the right side of the dialog box. So, for example, when a Windows Forms file is added to the project, the topmost node of the tree view (Visual C++) is concatenated with the backslash character. Next, the string UI is appended to this string (because it is the tree node that contains the Windows Forms item to be added), followed by another backslash. Finally, the name of the item shown in the right panel of the dialog box, the string Windows Form, is added, resulting in the string that can be passed to AddNewItem: Visual C++\UI\Windows Form. The second argument of this method is simply the name of the file to create, with the file name extension appended. If the file name parameter passed is an empty string, a default file name is generated and used.

image from book
Figure 8-2: The Add New Item dialog box for a Visual C# and a Visual C++ project

The ItemOperations object will add new and existing files to the selected project within Solution Explorer, but you will not always want to modify the selection to add an item to a specific solution. The ProjectItems collection has a series of methods for adding new and existing files to any project in a solution: AddFromDirectory, AddFromFileCopy, AddFromFile, and AddFromTemplate. AddFromDirectory accepts as a parameter the path to a folder on disk; this folder is searched recursively, causing all its contained files and subfolders to be added to the project. AddFromFileCopy and AddFromFile both perform the same basic operation, adding a reference to the specified file on disk to the project. However, AddFromFileCopy copies the file into the project's directory structure before adding this file to the project while AddFromFile adds a link to the item in whichever folder the file is contained. AddFromFileCopy differs from the AddFromTemplate method of the ProjectItems collection (not to be confused with the AddFromTemplate method of the Solution object) in that AddFromTemplate copies the file into the folder on disk for the project and then the project might make some modifications to the file after the files are added; if the template file has the .vstemplate extension, the template wizard is started and called to add the file to the project.

Here are the signatures, the parameters, and the meanings of the parameters for these methods:

 EnvDTE.ProjectItem AddFromDirectory(string Directory) EnvDTE.ProjectItem AddFromFileCopy(string FilePath) EnvDTE.ProjectItem AddFromFile(string FileName) EnvDTE.ProjectItem AddFromTemplate(string FileName, string Name) 

  • DirectoryThe source folder on disk. Searches for files and subfolders begin with this folder.

  • FilePath/FileNameThe location of the file to copy or add a reference to.

  • NameThe resulting name of the file. This name should have the extension of the file type.

Each of these methods returns a ProjectItem, an object that can be used to perform operations on the file that was added (such as opening the file or accessing the file's contents).

Note 

All of the Add methods on both the Solution and ProjectItems objects will return null or Nothing (depending upon the programming language you are using) if you pass a .vstemplate file as a template name. This is because a wizard could add 0, 1, or many items to a solution or project. If a wizard does not add any items, null or Nothing is a logical value to return. If multiple items are added, because the Add methods can return only one Project or ProjectItem object, null or Nothing is the correct value to return because the wizard would need to select one item arbitrarily to return. If the template wizard were to add one item, it would be confusing if a Project or ProjectItem object were returned, so, in this case, null or Nothing is also returned. Also, some of the Add methods will allow you to specify a target file name, but the wizard does not necessarily honor that target file name, so finding the item that you suggested a name for may not work. There is another reason for this value to be returned if you pass a .vstemplate as a template file: wizards do not have a mechanism for returning an item to Visual Studio indicating which item has been added, and without the ability to pass back an object, there is nothing to return other than null or Nothing.

Finding the path to an installed template for adding an item to a project is similar to finding a template for adding a project. For templates installed for all users, rather than using the GetTemplatePath method as you do for projects, you use the GetProjectItemTemplate for project items. This code uses the GetProjectItemTemplate method to find the path to the .vstemplate file for a Visual Basic module:

 Sub ProjectItemTemplatePath()     Dim Solution2 As EnvDTE80.Solution2     Dim VBModuleTemplatePath As String     solution2 = CType(DTE.Solution, EnvDTE80.Solution2)     VBModuleTemplatePath = _            solution2.GetProjectItemTemplate("Module.zip" ,_            "VisualBasic")     MsgBox(VBModuleTemplatePath) End Sub 

And just as for project templates installed by the user, you will need to use a brute-force strategy to find the path to the user-installed project item template. Project item templates are extracted into a folder named ItemTemplatesCache when the appropriate Add New Item dialog box is shown. This macro code will file a new project item template, named MyTemplate, for the Visual Basic language:

 Sub UserProjectItemTemplatePath()     Dim projectItemTemplatePath As String     projectItemTemplatePath = System.Environment.GetFolderPath _            (System.Environment.SpecialFolder.ApplicationData)     projectItemTemplatePath = System.IO.Path.Combine _            (projectItemTemplatePath, _            "Microsoft\VisualStudio\8.0\ItemTemplatesCache")     'projectItemTemplatePath contains the path for all templates,     'now add to the path     ' using information specific to the template to find:     projectItemTemplatePath = System.IO.Path.Combine _            (projectItemTemplatePath, _            "Visual Basic\MyTemplate.zip\MyTemplate.vstemplate") End Sub 

You might occasionally need to remove an item that has been added to a project because you no longer need it. The ProjectItem object supports two methods for removing items from the project: Remove and Delete. These two methods both remove an item from the project, but Delete is more destructive because it also erases the file from disk by moving it into the computer's Recycle Bin.




Working with Microsoft Visual Studio 2005
Working with Microsoft Visual Studio 2005
ISBN: 0735623155
EAN: 2147483647
Year: 2006
Pages: 100

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net