TFS 2010 Beta 2 – Custom Work Item Controls. Step 2, Work Item Setup


[Edit: Source code for the control discussed in this post can be found here: TFS TimeSheets (Codeplex).]

In the first post (Step 1, Getting Started) in this series I looked at how to create a basic Work Item Custom Control for Team Foundation Server 2010, and went through the process of configuring and installing the custom control for use on the Task work item.

Today I’m looking at setting up the Task Work item definition to allow create a new field for our custom work item control to persist time sheet data to.

The screen shot below depicts my goals for the control; however this post focuses more on how to create and configure the control than the actual time sheeting ability itself. Yes, I know this one isn’t going to win any prizes for prettiness … but that can be fixed later 🙂

As we are restricted within Team Foundation Server to a non-relational structure for our work item data, my current thinking is that time sheet data will be stored as XML within a new field configured on the work item. The other option I considered was looking at the ‘History’ field type … but a bit of investigation suggests that the way the work item history control works is to look at the various revisions of the work item, rather than store a collection of values.


Before getting started, the following prerequisite setup should be completed:

  • Visual Studio 2010 Beta 2 (for development)
  • Visual Studio 2010 Team Explorer Beta 2 (for testing)
  • Team Foundation Server 2010 Beta 2
  • The output from the project setup in Step 1.
  • A new reference added to our custom control library to Microsoft.TeamFoundation.Client
  • A new reference added to our custom control library to Microsoft.TeamFoundation.WorkItemTracking

Modify the Work Item Template

Using the following command the existing work item template for the Task work item can be extracted from the Team Foundation Server.

C:\>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin.exe” exportwitd /collection:localhost\defaultcollection /p:”{ExistingProject}” /n:Task /f:Task.xml

If you haven’t worked with the work item template in the past, at this stage it’s worth having a good read through the documentation. For the purposes of the changes today we are only going to need to add a new field; however there is a lot of value in understanding some of the other features available within the schema.

The first thing we need to do is declare a new field to store the time sheet data. The XML fragment below shows the new field definition is black bold font. It should be noted that the refname is unique across the entire Team Foundation Server collection database, so be sure to apply a suitable name at this stage. I tend to prefix all my custom fields with ‘Custom’ just to make them easier to identify.

<FIELD name=Authorized As refname=System.AuthorizedAs type=String syncnamechanges=true />
<FIELD name=”TimesheetRawData” refname=”Custom.Timesheets.TimesheetRawData” type=”PlainText” />

We also need to add the FieldName attribute to the control definition for the WorkItemTimeSheetControl:

<Tab Label=TimeSheets>
<Control Type=WorkItemTimeSheetControl LabelPosition=Top FieldName=”Custom.Timesheets.TimesheetRawData” />

The modified work item can then be imported back into TFS 2010 using the following command:

C:\TFS>”C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\witadmin.exe” importwitd /collection:localhost\defaultcollection /p:”{ExistingProjectName}” /f:Task.xml

Using the IWorkItemControl Members

The Work Item Custom Control we created earlier implemented the IWorkItemControl interface. Using this interface we can get access to the currently loaded work item, and manipulate its values programmatically.

The full documentation for the interface can of course be found on MSDN, but below are my additional notes on the usage of some of the members.

WorkItemDataSource A reference to the work item is provided to the user control via the WorkItemDataSource property. The property itself is defined as an object, but so far I’ve found that this reference can be safely typecast to a stronger type of Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem.
WorkItemFieldName If the work item control has been setup with a fieldname value then this will be provided to the custom control via the WorkItemFieldName field.
InvalidateDataSource The InvalidateDataSource method is called during the loading (and unloading) of a work item. This method should be used to populate the fields of the Work Item Custom Control with their persisted values, or default values for a new work item.

Writing to the Work Item using the Object Model

A small number of standard properties may be set via strongly typed properties on the Work Item … however the majority of the Work Item data must be accessed from within the Fields collection.

CurrentWorkItem.Fields[WorkItemFieldName].Value = TimeSheet.Serialize(TimeSheet);

Whenever any data is changed within the Fields collection the work item interface automatically detects that the work item is ‘dirty’ and sets it to appear modified in the user interface with the * next to the work item name.

The one gotcha I did come across on the way was how to obtain the name of the current user in the context of the connection to Team Foundation Server. It turns out this can be retrieved from the following property:


The changes I’ve made to the control at this point have been very basic. I’ve added a couple of user input controls to the form, and setup the add button handler to add a new time sheet entry entity to a time sheet list, then serialize the resulting list back to the work item based on the WorkItemFieldName.

At a high level, the functionality implemented is:

  • Ability to enter a new timesheet entry
  • Ability to view all timesheet entries associated to the work item
  • The value of Remaining Work is decreased automatically based on the minutes entered
  • The value of the Completed Work is increased automatically based on the minutes entered

Testing the Changes …

As before, it is necessary to reopen the testing instance of Visual Studio 2010 – otherwise the old work item definition may still be cached.

If we reopen Visual Studio then create a new Task work item our custom control should be displayed under the TimeSheets tab, and loading / saving Task work items should result in our changes being persisted to the database.


While working through this investigation process I’ve found the following resources very useful, and my thanks go to their authors:


  1. Hi Nick
    Can you share the code for this screen shot above depicts? I’m working on develop a exactly almost same with your control, I’m working for Hardware have no much experience on program, I don’t know how to binding TFS data with control fields, if you are working in MS, my alias is: smartli.

    Thank you advance

    • Hi Smart,

      What specifically was the issue you are encountering? Perhaps I should post a little more detail to help others out with the same problem.

      I don’t have the code in a tidy enough state to publish publicly on the web at the moment, but I’ll see if I can dig up the sample to send you over the weekend. I’m not working for MS so can’t send directly to your internal alias … will work?



      • Yes, after read your blog, and with my frident’s helps, we developed one similar one as yours, it’s works, Thanks

  2. Hi Nick,

    great post, quick question how do i go about creating a new ‘State’ apart from the default Active/Closed/Resolved?



  3. hi, your post is very intresting, since at my company we are planning to develop a very similar customization…can you provide me the code? or at least more details on how to interact with datasource to store/retrieve persistent timesheet data?

    thank you in advance.

  4. Hi, this is just what we are looking for. Can you point me in the right direction for the steps to install this into tfs.


    • Hi Arno,

      I’ve been concidering that for a while – but just haven’t gotten around to it. Having said that, nobody else has been interested in contributing up until now, so I haven’t put any time aside for it.

      I can’t do this tonight, but I’ll try to set something up over the next few days.



  5. Nick,

    Very nice, thanks for posting this. I ran the setup and did the relevant parts of your part1 and part2 post. I get the timesheet tab correctly displayed on a new work item as above. When I hit the Add button, VS throws an error and restarts. Any idea what is causing this? I’m on VS/VSTS 2010.


    • Hi Tim,

      Please to hear that the post was useful – it’s always nice to get positive feedback 🙂

      In terms of the error you are encountering … I haven’t seen this crash Visual Studio in the past, so I’m a bit surprised. Is there currently any logic within your Add button? Is there a try/catch built around it that could perhaps provide some clues as to what exception is being raised?

      If you are able to post the Add button handler I’m happy to have a look. Also, there is an updated version of the source code at if that is of any help to you.



  6. Nick,
    I’m just using the control build you posted. I’ll download the source and try my own build. Might be related to my 64bit Win7 desktop.

  7. Nick,

    My bad. I added the control to a workitem type I created that didn’t have remaining and completed work fields. Works great now.

    Thanks again,

    • Hi Tim,

      Good to hear it has all worked out. Does make me wonder whether I have nice enough error messages on the latest build though. I’ll add it as an issue and check it out next time I’m working on the code.



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s