This post was written by Hayder Casey, a developer on the work item tracking team.
If you have used Visual Studio 2010, you may have noticed the new “Connect to Team Project” dialog:
This replaced the old DomainProjectPicker in Visual Studio 2008. The main change you will notice is the introduction of the left pane, Team Project Collections. This is because in TFS 2008, the server only had one project collection and it was synonymous with the server. A 2010 server can have multiple collections.
Another feature of the dialog is that all server trips are done on the background thread, so it never blocks the UI. The dialog can be dismissed or the selected server can be changed at any time.
Like the previous DomainProjectPicker dialog, the TeamProjectPicker dialog API is public and can be reused in your own application.
The dialog has three selection modes:
Select a Team Project Collection Only:
Select a single team project:
Select multiple team projects: (notice the checkboxes in the Team Projects panel)
Namespace: Microsoft.TeamFoundation.Client Assembly: Microsoft.TeamFoundation.Client.dll
public class TeamProjectPicker : IDisposable { public TeamProjectPicker(); public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange); public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange, ICredentialsProvider credentialsProvider); public string AcceptButtonText { get; set; } public string Text { get; set; } public TfsTeamProjectCollection HostActiveTeamProjectCollection { get; set; } public ProjectInfo[] SelectedProjects { get; set; } public TfsTeamProjectCollection SelectedTeamProjectCollection { get; set; } public event CancelEventHandler AcceptButtonClick; public void Dispose(); public void SetDefaultSelectionProvider(ITeamProjectPickerDefaultSelectionProvider provider); public DialogResult ShowDialog(); public DialogResult ShowDialog(IWin32Window parentWindow); }
public class TeamProjectPicker : IDisposable
{
public TeamProjectPicker();
public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange);
public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange, ICredentialsProvider credentialsProvider);
public string AcceptButtonText { get; set; }
public string Text { get; set; }
public TfsTeamProjectCollection HostActiveTeamProjectCollection { get; set; }
public ProjectInfo[] SelectedProjects { get; set; }
public TfsTeamProjectCollection SelectedTeamProjectCollection { get; set; }
public event CancelEventHandler AcceptButtonClick;
public void Dispose();
public void SetDefaultSelectionProvider(ITeamProjectPickerDefaultSelectionProvider provider);
public DialogResult ShowDialog();
public DialogResult ShowDialog(IWin32Window parentWindow);
}
public enum TeamProjectPickerMode{ NoProject, SingleProject, MultiProject}
disableCollectionChange: if true, will not allow changing the selected server and collection (you can only change the selected projects). You should not pass true here if you are using TeamProjectPickerMode.NoProjectMode.
public class ProjectInfo{ public ProjectInfo(string uri, string name, ProjectState status); public string Name; public ProjectState Status; public string Uri;}
In Visual Studio, the connect dialog will remember the user’s previous selection. Say the user connects to Server A, then selects collection B and connects to a couple team projects. Next time the connect dialog is invoked, Server A, collection B, and the previous projects will be automatically selected. Those previous selections are stored on the client and used in the connect dialog by default. However, if you want to use your own defaults instead of the ones from the Visual Studio client, you can implement you own ITeamProjectPickerDefaultSelectionProvider for the dialog to use. Here are the interface members: public interface ITeamProjectPickerDefaultSelectionProvider{ Uri GetDefaultServerUri(); // The Uri of the server to be selected by default Guid? GetDefaultCollectionId(Uri instanceUri); // Given a server Uri, returns the selected collection Id; you can return null here (no collection will be selected) IEnumerable<string> GetDefaultProjects(Guid collectionId); // The default projects for a given collection. If used with NoProject selection mode, you can return null here. If you are using SingleProject selection mode, you should only return a list of 1 item. The string here is the project Uri.}
In Visual Studio, the connect dialog will remember the user’s previous selection. Say the user connects to Server A, then selects collection B and connects to a couple team projects. Next time the connect dialog is invoked, Server A, collection B, and the previous projects will be automatically selected. Those previous selections are stored on the client and used in the connect dialog by default. However, if you want to use your own defaults instead of the ones from the Visual Studio client, you can implement you own ITeamProjectPickerDefaultSelectionProvider for the dialog to use. Here are the interface members:
public interface ITeamProjectPickerDefaultSelectionProvider{ Uri GetDefaultServerUri(); // The Uri of the server to be selected by default Guid? GetDefaultCollectionId(Uri instanceUri); // Given a server Uri, returns the selected collection Id; you can return null here (no collection will be selected) IEnumerable<string> GetDefaultProjects(Guid collectionId); // The default projects for a given collection. If used with NoProject selection mode, you can return null here. If you are using SingleProject selection mode, you should only return a list of 1 item. The string here is the project Uri.}
Here is some sample console application code that invokes the dialog with MultiProject selection mode and then prints the selection to the console output.
You will need to reference the following assemblies:
using System.Windows.Forms; using Microsoft.TeamFoundation.Client; using Microsoft.TeamFoundation.Server; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Application.EnableVisualStyles(); // Makes it look nicer from a console app. //"using" pattern is recommended as the picker needs to be disposed of using (TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.MultiProject, false)) { DialogResult result = tpp.ShowDialog(); if (result == DialogResult.OK) { System.Console.WriteLine("Selected Team Project Collection Uri: " + tpp.SelectedTeamProjectCollection.Uri); System.Console.WriteLine("Selected Projects:"); foreach(ProjectInfo projectInfo in tpp.SelectedProjects) { System.Console.WriteLine(projectInfo.Name); } } } } } }
using System.Windows.Forms;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
namespace ConsoleApplication1
class Program
static void Main(string[] args)
Application.EnableVisualStyles(); // Makes it look nicer from a console app.
//"using" pattern is recommended as the picker needs to be disposed of
using (TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.MultiProject, false))
DialogResult result = tpp.ShowDialog();
if (result == DialogResult.OK)
System.Console.WriteLine("Selected Team Project Collection Uri: " + tpp.SelectedTeamProjectCollection.Uri);
System.Console.WriteLine("Selected Projects:");
foreach(ProjectInfo projectInfo in tpp.SelectedProjects)
System.Console.WriteLine(projectInfo.Name);
What if I want to implement my own connection experience? Is there an API I can use?
The APIs used in the connect dialog are public and you can implement your own connection experience with reasonable effort.
I suggest you start by reading this blog post by Taylor Lafrinere: Retrieve the List of Team Project Collections from TFS 2010 Client APIs.
After you read the blog post, and you started to write your own dialog, you may realize that you still need a way to get a list of servers that the user previously connected to. In 2008, we had the RegisteredServer class, but now it’s obsolete. The new replacement is RegisteredTfsConnections class.
RegisteredTfsConnections manages a list of previously connected to server (TfsConfigurationServer) and collections (TfsTeamProjectCollections). The API is straight forward to use. Here are its members:
public static class RegisteredTfsConnections { public static RegisteredConfigurationServer GetConfigurationServer(string name); public static RegisteredConfigurationServer GetConfigurationServer(Uri uri); public static RegisteredConfigurationServer[] GetConfigurationServers(); public static void RegisterConfigurationServer(TfsConfigurationServer configurationServer); public static void UnregisterConfigurationServer(string name); public static RegisteredProjectCollection[] GetLegacyProjectCollections(); public static RegisteredProjectCollection GetProjectCollection(string name); public static RegisteredProjectCollection GetProjectCollection(Uri uri); public static RegisteredProjectCollection[] GetProjectCollections(); public static void RegisterProjectCollection(TfsTeamProjectCollection projectCollection); public static void UnregisterProjectCollection(string name); }
public static class RegisteredTfsConnections
public static RegisteredConfigurationServer GetConfigurationServer(string name);
public static RegisteredConfigurationServer GetConfigurationServer(Uri uri);
public static RegisteredConfigurationServer[] GetConfigurationServers();
public static void RegisterConfigurationServer(TfsConfigurationServer configurationServer);
public static void UnregisterConfigurationServer(string name);
public static RegisteredProjectCollection[] GetLegacyProjectCollections();
public static RegisteredProjectCollection GetProjectCollection(string name);
public static RegisteredProjectCollection GetProjectCollection(Uri uri);
public static RegisteredProjectCollection[] GetProjectCollections();
public static void RegisterProjectCollection(TfsTeamProjectCollection projectCollection);
public static void UnregisterProjectCollection(string name);
Notes:
RegisteredConfigurationServers represent the server; this is a new concept in 2010. Each server can contain multiple team project collections. A 2008 server is treated in this API as a ProjectCollection. Thus, in the connect dialog server list, we list both:
The name parameter in the above API is the friendly name of the server or collection.
How do I get the actual server object and connect to it after getting this RegisteredConfigurationServer or RegisteredProjectCollection?
You can use the server factories to get server objects:
public static class TfsConfigurationServerFactory { public static TfsConfigurationServer GetConfigurationServer(RegisteredConfigurationServer application); public static TfsConfigurationServer GetConfigurationServer(Uri uri); public static TfsConfigurationServer GetConfigurationServer(RegisteredConfigurationServer application, ICredentialsProvider fallbackCredentialsProvider); public static TfsConfigurationServer GetConfigurationServer(Uri uri, ICredentialsProvider fallbackCredentialsProvider); } public static class TfsTeamProjectCollectionFactory { public static TfsTeamProjectCollection GetTeamProjectCollection(RegisteredProjectCollection projectCollection); public static TfsTeamProjectCollection GetTeamProjectCollection(Uri uri); public static TfsTeamProjectCollection GetTeamProjectCollection(RegisteredProjectCollection projectCollection, ICredentialsProvider fallbackCredentialsProvider); public static TfsTeamProjectCollection GetTeamProjectCollection(Uri uri, ICredentialsProvider fallbackCredentialsProvider); }
public static class TfsConfigurationServerFactory
public static TfsConfigurationServer GetConfigurationServer(RegisteredConfigurationServer application);
public static TfsConfigurationServer GetConfigurationServer(Uri uri);
public static TfsConfigurationServer GetConfigurationServer(RegisteredConfigurationServer application, ICredentialsProvider fallbackCredentialsProvider);
public static TfsConfigurationServer GetConfigurationServer(Uri uri, ICredentialsProvider fallbackCredentialsProvider);
public static class TfsTeamProjectCollectionFactory
public static TfsTeamProjectCollection GetTeamProjectCollection(RegisteredProjectCollection projectCollection);
public static TfsTeamProjectCollection GetTeamProjectCollection(Uri uri);
public static TfsTeamProjectCollection GetTeamProjectCollection(RegisteredProjectCollection projectCollection, ICredentialsProvider fallbackCredentialsProvider);
public static TfsTeamProjectCollection GetTeamProjectCollection(Uri uri, ICredentialsProvider fallbackCredentialsProvider);
There are also some setting you can set on the RegisteredProjectCollection:
public sealed class RegisteredProjectCollection{ public bool AutoReconnect { get; set; } public string Name { get; } public bool Offline { get; set; } public Uri Uri { get; }}
AutoReconnect: flag to determine if Team Explorer will auto reconnect to this collection upon start up if it is the most recently connected collection. Offline: If true, a version control bound project will not go online and load the TF server automatically. Name: Collection friendly name; usually in the form of “server\collection” Uri: The collection Uri; example: “http://companyServer:8080/tfs/mycollection”