Copy area and interation structure using the Area Import/Export Tool

If you look for a way to export and import your area and/or iteration structure the Team Foundation Object Model (TFOM) is your friend.

However it’s only your friend if you know where to look for.

While the export works perfectly using the WorkItemStore, the import is only possible through the ICommonStructureService (and could be used for export as well).

At the bottom you can download the source code of TFS Area Import/Export Tool.


It saves your area and/or iteration structure into a text file and lets you import it into another project (even on another Team Foundation Server).

Feedback is appreciated.

Version 1.0.2 – compiled against Team Explorer 2010

Version 1.0.1 – compiled against Team Explorer 2008
File Attachment: (25 KB)

Version 1.0.0 – compiled against Team Explorer 2005
File Attachment: (69 KB)

Download: Visual Studio 2005 Project Template for TFS Utilities

If you develop small utilities for Team Foundation Server a lot you might want to save some time and use a project template (see bottom for file attachment) that already comes equipped with the correct references to all Microsoft.TeamFoundation.*.dlls as well as the most important using statements and a few lines of code to get started.


Copy the ZIP file to {MyDocuments}\Visual Studio 2005\Templates\ProjectTemplates.


Create a new project and select “TFS Utility” from the “My Templates” list.


The template creates a new Windows Forms application with references to the Microsoft.TeamFoundation.*.dlls (btw: the C# compiler gets rid of all references that were not used in the project during compilation)…


… as well as a a few using statements and some code to start from.


Happy TFS tool development!

File Attachment: TFS (16 KB)

Update (Nov 13, 2011): There are updated versions available for VS 2008 and VS 2010.

Getting started using Custom Work Item Controls

Since Service Pack 1 [1] we have the ability to create our own controls to display field value within a work item form which gives us great flexibility.

However there are two caveats with custom work item controls right now that aren’t solved:

  • They do not work with Web Access [2] so it’s not a choice for people that heavily rely on the web client.
  • They need to be deployed to the machine of every user accessing TFS.

Setting the stage

As an first realistic example we could make the priority field a little prettier. I mean the allowed values “1”, “2”, and “3” are not very descriptive. We don’t want to create a new field or change the values since we used this field already. So the solution would be to create a custom work item control on top of the existing values that displays something else.

I plan to create a new control that has a combobox on it and will display something nicer than the real values that are stored in the database. The complete source code is attached for reference.

1. Create the Work Item Control

A custom work item control is essentially a regular Windows Forms control. It has to derive from Control and implement IWorkItemControl.

The loading takes place in IWorkItemControl.InvalidateDatasource, the saving in IWorkItemControl.FlushToDatasource. The bold code indicates peaces that were necessary to implement my wishes. The rest is infrastructure and is repeated for every control you’ll write.

Here’s the code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.TeamFoundation.WorkItemTracking.Controls;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace TeamSystemPro.Samples.WorkItemControls
    /// Work Item Control for displaying the priority (can be 1,2, or 3 in MSF) in a more descriptive way then just showing the numbers.
    /// Custom controls need to derive from Control.
    /// Typically custom controls are built from UserControl.
    /// The control needs to implement IWorkItemControl.
    /// This is defined in Microsoft.TeamFoundation.WorkItemTracking.Controls.dll assembly that can be found from VS installation folder, typically ":\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies".
    /// Add reference to that assembly and line "using Microsoft.TeamFoundation.WorkItemTracking.Controls;" in code.  
    /// How it works:
    ///   After the control is loaded, a reference to work item is passed to the control using IWorkItemControl.WorkItemDatasource property.
    ///   The control is asked to display its data using IWorkItemControl.InvalidateDatasource method.
    ///   The control is required to update any values directly in WorkItem object itself when user changes data. 
    public partial class PriorityControl : UserControl, IWorkItemControl
        private WorkItem workItem;
        private string workItemFieldName;
        private IServiceProvider serviceProvider;
        private System.Collections.Specialized.StringDictionary properties;
        private bool readOnly = false;

        public PriorityControl()

        #region IWorkItemControl Members

        /// Raise this events before updating WorkItem object with values. When value is changed by a control, work item form asks all controls (except current control) to refresh their display values (by calling InvalidateDatasource) in case if affects other controls 
        public event EventHandler BeforeUpdateDatasource;

        /// Raise this event after updating WorkItem object with values. When value is changed by a control, work item form asks all controls (except current control) to refresh their display values (by calling InvalidateDatasource) in case if affects other controls 
        public event EventHandler AfterUpdateDatasource;

        /// Control is asked to clear its contents
        void IWorkItemControl.Clear()
            cboPriorities.SelectedIndex = -1;

        /// Control is requested to flush any data to workitem object. This usually happens during save operation or when the form is left. In most cases data will be written to workitem immediately on change and hence this will not need implementation. Some customers want a way to do operations during save, and this is the closest thing we got. If you do need a way to react to before-save & after-save events, pls let us know in forums given below and we'll consider for future revision.
        void IWorkItemControl.FlushToDatasource()
            this.BeforeUpdateDatasource(this, EventArgs.Empty);
            workItem.Fields[workItemFieldName].Value = Convert.ToString(cboPriorities.SelectedIndex + 1);
            this.AfterUpdateDatasource(this, EventArgs.Empty);

        /// Asks control to invalidate the contents and redraw. At this point, control can read from work item object and display/refresh data.
        void IWorkItemControl.InvalidateDatasource()
            if (IsInitialized())
                int currentValue = (int)workItem.Fields[workItemFieldName].Value;
                cboPriorities.SelectedIndex = currentValue - 1;

        /// A property bag of all attributes specified in work item form xml for this control. Custom attributes are allowed and can be used to pass parameters specific for this control from work item type xml.
        System.Collections.Specialized.StringDictionary IWorkItemControl.Properties
            get { return properties; }
            set { properties = value; }

        /// Tells the control to display in readonly mode.
        bool IWorkItemControl.ReadOnly
            get { return readOnly; }
            set { readOnly = value; OnReadOnlyChanged(); }
} /// /// Gives pointer to IServiceProvider if you intended to access Document service or VS Services. If services are not needed, do nothing in this method. /// /// void IWorkItemControl.SetSite(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } /// /// This passes reference to source work item object. Cast this object to WorkItem type. /// object IWorkItemControl.WorkItemDatasource { get { return workItem; } set { workItem = value as WorkItem; } } /// /// The field name if the control is associated with a field name in work item form xml. A custom control can be associated with 0 or 1 work item field. /// string IWorkItemControl.WorkItemFieldName { get { return workItemFieldName; } set { workItemFieldName = value; } } #endregion private bool IsInitialized() { return (!this.IsDisposed && workItem != null && !string.IsNullOrEmpty(workItemFieldName) && workItem.Fields.Contains(workItemFieldName)); } private void OnReadOnlyChanged() { cboPriorities.Enabled = !readOnly; } } }

Additionally you need to create an XML file with the .wicc extensions which contains the name of your assembly file as well as the full-qualified name (i.e. namespace and classname) of your control class:


So you have your control as well as the .wicc-file (which is necessary for registration):


2. Deploy the Work Item Control

Although you could simply copy the two files (.dll and .wicc) to the “Microsoft\Team Foundation\Work Item Tracking\Custom Controls” under Environment.SpecialFolder.CommonApplicationData (we could also use the folder unter then under Environment.SpecialFolder.LocalApplicationData), but I decided to create a new MSI setup with Visual Studio which might look like this:


3. Reference the new control in a Work Item Type

After the control is deployed just change the type attribute for the control in the work item type XML. The Type should reference the name of the .wicc-file.


Now you can import your modified work item type XML (you need to use witimport as the Process Template Editor does not support custom controls right now), refresh the cache by right-clicking the Work Items node in Team Explorer and press “Refresh”.


Further recommended reading:

  • How to use Custom Controls in Work Item Form [3]
  • Communicating between custom controls: Building parent/child controls [4]

Enjoy increasing your Work Item UI experience through custom controls!






File Attachment: (25 KB)

Undocumented attributes for controlling the Work Item form layout

Naren [1] revealed a few very interesting on hidden attributes his blog [2] which you definitely should take a look at since they let you solve some problems as the following ones:

Control the height of two text boxes that were placed vertically on one tab

When placing more than one text box on a tab page you will notice that all text boxes have the same height except the last one which can be annoying if you use HTML and expect the writer to write a lot.


Using the “MinimumSize” attribute in the Work Item Type XML you can specify the minimum width and height that the control has to have.


Resulting in a much more nice looking writing experience:


Show the same field twice in different places

Sometimes it makes sense to place the same field on two places for example in the general area as well as on a tab. If you do so you would get an error.


You can use “Name” attributes with different values to allow the field to be displayed multiple times.


This leads to the desired effect. Note that if you enter something in the one field it will automatically appear in the other text field after leaving the control.


So here’s the background by Naren. A must read for people customizing Work Item types:

<Control FieldName=”control name” Type=”FieldControl | DateTimeControl | HtmlFieldControl | LinksControl | AttachmentsControl | WorkItemClassificationControl | WorkItemLogControl” Label=”label text” LabelPosition=”Top | Bottom | Left | Right” Dock=”Fill | Top | Bottom | Left | Right” Padding=”(left, top, right, bottom)” Margin=”(left, top, right, bottom)” ReadOnly=”True | False” />


Attributes that weren’t documented:


MinimumSize: The minimum size the control should occupy in the form. If vertical space is not enough, then a scrollbar is shown to keep its minimum size. Without this attribute, the controls are drawn with their default sizes (unless controls in other tabs take larger space that incrasing whole tab’s size). The syntax for it’s value is “(width,height)” (In regex format it is “^\(\d+\,\d+\)$”).


Name: If you want to add same field to be displayed in more than one place, it is possible but the Name attribute should be set to unique values for both – so that the system identifies each control uniquely. It is useful to show same control in various places based on context of tabs.


[Update: 3/12/07]

Below are special attributes available for specific controls:

NumberFormat (for FieldControl only): Useful if a number value is displayed in the field. Possible values: WholeNumbers, SignedWholeNumbers, DecimalNumbers, SignedDecimalNumbers. Setting this attribute determines what characters are allowed to be entered in this control.


MaxLength (for FieldControl only): Maximum length of allowed characters for field control in form UI.


Format (for DateTimeControl only): One of values of DateTimePickerFormat enum. Possible values as given in help are: Long, Short, Time and Custom. Custom format can be set by having ‘Custom’ as value for this attribute, and setting another attribute named CustomFormat with actual custom format string.




Use SnagIt to capure your screen and create a new Work Item quickly

Capturing screenshots and new bugs quickly is a everyday task for software developers and testers.

The default Work Item form does not handle this scenario very efficiently, i.e. you have to click too many times until the new bug is created.

One nice solution comes out of TechSmith, the creators of the popular SnagIt screen capture tool. As Betsy Weber announced it they made a New “SnagIt Output for Microsoft Visual Studio Team System” [1] available which lets you create new Work Items with screenshots attached or update existing ones with ease.

Let’s try how it looks like…

  1. You take a capture of your screen using SnagIt.


  2. You use one of SnagIt’s diverse editing functions to make clear what’s the problem is (e.g. arrows, or text).


  3. You click the new “Team System” bottom in the toolbar and select “New Work Item” if there is no work item existing already.


  4. You supply connection information to your Team Foundation Server as well as which type of work item you want to create, what the name of the attached file and the associated comment should be.


  5. After hitting “Create” you get the well-known Work Item form where you could supply more details on the bug.


  6. Alternatively you can also add the screenshot to an already existing work item by hitting “Update Work Item” from the Team System toolbar menu.


  7. This let’s you search for the bug and updating it’s attachments.


  8. In either way the result is a nicely attached screenshot in your work item.


You can also watch a video [2] by TechSmith of the new output in Action.