Freigeben über


Work Item Tracking Custom Controls

 

(Many thanks to Hayder Casey, who provided this great write-up on work item tracking custom controls. He’s a developer who works on the TFS Work Item Tracking team with me. Thanks Hayder!)

Custom Controls provide a mechanism to extend the work item form to include user developed controls. It enables various scenarios, that are difficult or not possible using the built in controls such as: extend event-based rules, custom user interface, workflow capabilities. More details about custom control capabilities and restrictions are found in the WIT Custom Controls msdn article.

We have a codeplex project: Custom Control for TFS Work Item Tracking, you can find more details, and source code for useful custom controls.

Implementation

Custom control should derive from System.Windows.Forms.Control and implement IWorkItemControl interface and optionally implement IWorkItemToolTip, IWorkItemUserAction, and IWorkItemClipboard. These interfaces are in Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

IWorkItemControl

This is the interface that all custom control (actually even built in controls) implements. It provides basic functionality to interact with the workitem object and the form. Let’s take a look at its definition:

 

    public interface IWorkItemControl

    {

        object WorkItemDatasource { get; set; }

        string WorkItemFieldName { get; set; }

        StringDictionary Properties { get; set; }

        bool ReadOnly { get; set; }

 

        event EventHandler AfterUpdateDatasource;

        event EventHandler BeforeUpdateDatasource;

 

        void Clear();

        void FlushToDatasource();

        void InvalidateDatasource();

        void SetSite(IServiceProvider serviceProvider);

    }

 

WorkItemDatasource
Passes a reference to the WorkItem object (cast it to Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem). During initialization this get set to null, so make you take that into account when using the property.

 

WorkItemFieldName

The name of the field the control is associated with. However it’s possible for control to not be associated with a specific field. For example the LinksControl always work with the work item links and not associated with a field while the DateTimeControl is always associated with a field.

 

Properties

A property bag of all attributes specified in the work item form xml for this control. There are a set of standard attributes (Padding, Margin, Dock, …etc ) see The Control element article on msdn for a complete list of attributes. These standard attributes are automatically parsed and applied to your control, so you don’t need to do anything. Besides those you can supply custom attributes, there are no restriction to the attribute name. For example you can specify a color attributes in the xml, then in your implementation you can read this attributes and set your control color accordingly. In 2010 we also allow you to specify an xml element “CustomControlOptionsType”.

 

Here is the control type schema used for the wit definition, highlighted is new for 2010:

    <xs:complexType name="ControlType">

       

 <xs:element name="CustomControlOptions" type="CustomControlOptionsType" minOccurs="0" maxOccurs="1" />

       

<xs:attribute name="FieldName" type="typelib:ReferenceFieldName" use="optional" />

        <xs:attribute name="Type" type="ValidControlsType" use="required" />

        <xs:attribute name="Label" type="LabelType" use="optional" />

        <xs:attribute name="LabelPosition" type="LabelPositionType" />

        <xs:attribute name="Dock" type="DockType" use="optional" />

        <xs:attribute name="Padding" type="PaddingType" use="optional" />

        <xs:attribute name="Margin" type="PaddingType" use="optional" />

        <xs:attribute name="ReadOnly" type="ReadOnlyType" use="optional" />

        <xs:attribute name="MinimumSize" type="SizeType" use="optional" />

        <xs:attribute name="Name" type="NonBlankString" use="optional" />

        <xs:anyAttribute processContents="skip"/>

    </xs:complexType>

 

    <xs:complexType name="CustomControlOptionsType">

      <xs:sequence>

        <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>

      </xs:sequence>

    </xs:complexType>

 

 

The CustomControlOptions is accessible to you control using IWorkItemControl.Properties[“innerxml”].

 

ReadOnly

Tells the control to display in read only mode.

 

BeforeUpdateDatasource/AfterUpdateDatasource

Implement and raise those events when before and after you flush user input to the datasource.

 

Clear

Clear the control content.

 

FlushToDatasource

Control is requested to flush any data to workitem object. This usually happens during save operation. In most cases data should be written to workitem immediately on user change.

 

InvalidateDatasource

Asks control to invalidate the contents and redraw. At this point, control can read from work item object and display/refresh data.

 

SetSite

Gives pointer to IServiceProvider if you intended to access DocumentService or other VS Services. If services are not needed, do nothing in this method.

 

We have added a new service in 2010 IWorkItemControlHost. Simply call serviceProvider.GetService(typeof(IWorkItemControlHost))). Here is the interface definition, might be useful to you if you want to interact with Microsoft Office:

    [Guid("c823b363-9cb6-4be4-baa3-bc4154409114")]

    public interface IWorkItemControlHost

    {

        void ShowWorkItem(WorkItem workItem);

        void ShowQueryResults(TfsTeamProjectCollection teamProjectCollection, string teamProjectName, string queryText);

        void SendToExcel(TfsTeamProjectCollection teamProjectCollection, string teamProjectName, List<string> fieldNames, List<int> workItemIds);

        void SendToProject(TfsTeamProjectCollection teamProjectCollection, string teamProjectName, List<string> fieldNames, List<int> workItemIds);

        void SendToMail(TfsTeamProjectCollection teamProjectCollection, string teamProjectName, List<string> fieldNames, List<int> workItemIds);

        bool SupportsSendToExcel { get; }

        bool SupportsSendToProject { get; }

        bool SupportsSendToMail { get; }

    }

 

IWorkItemToolTip

Implement this interface if you want the custom control’s Label to have a tooltip.

 

    public interface IWorkItemToolTip

    {

        ToolTip ToolTip { get; set; }

        Label Label { get; set; }

    }

 

When both the ToolTip and the Label are set, just call ToolTip.SetToolTip(Label, "This is a custom tool tip”). Well you probably want to make it useful, the standard control put the field reference name in the tooltip. You could also do something complicated such as showing the field history in the tooltip.

 

IWorkItemUserAction

Implement this if your control might require user action. user action required means the item is in a bad state and cannot be saved.

 

   public interface IWorkItemUserAction

    {

        string RequiredText { set; get; }

        Color HighlightBackColor { set; get; }

        Color HighlightForeColor { set; get; }

        bool UserActionRequired { get; }

        event EventHandler UserActionRequiredChanged;

    }

 

RequiredText: Friendly error message, will be displayed in the infobar in VS.

HighlightBackColor/ForeColor: use these colors in your control if a user action is required so its consistent with the rest of controls on the form.

UserActionRequired: tell them form if the control need input from the user

UserActionRequiredChanged: Raise this event if the UserActionRequired Property changes

 

IWorkItemClipboard

Implement this if you want your control to work with VisualStudio edit menu (Cut/Copy/Paste). Basically fire ClipboardStatusChanged if any of the Can* method might change.

    public interface IWorkItemClipboard

    {

        bool CanCut { get; }

        bool CanCopy { get; }

        bool CanPaste { get; }

        void Cut();

        void Copy();

        void Paste();

        event EventHandler ClipboardStatusChanged;

    }

 

Deployment

 

Adding the custom control to the form definition

To use the control in a form you will need to modify the form definition on the server. the easiest way to download a form you want to modify using the exportwitd command, modify it to use the custom control then upload the modified xml using importwitd. The tool to import/export work item definition is witadmin.exe (Run  “witadmin help importwitd “and “witadmin help exportwitd” to get help on using those commands). To specify custom control in the form simply locate the Form section in the type xml and modify or add a Control element. Here is an example of using a MultiValueControl from the codeplex project:

<Control Type="MultiValueControl" FieldName="Microsoft.VSTS.Common.Triage" Label="Triag&amp;e:" LabelPosition="Left" />

This is just like any other control definition, the syntax is the same, in fact, the import tool (for the most part) doesn’t distinguish between built-in control and a custom controls, it’s just a name for a control.

 

Deployment Folders

After you created a custom control (as part of a dll or an exe) you will need to drop both the dll and wicc file in one of the custom control folder both should be In the same folder unless the wicc file specifies a full path to the assembly.

 

Here are the locations that we look for custom controls in Visual Studio 2010. We search in this order. If one is found in one of these folders we will use it and not look further:

1. All ValueNames under " HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\WorkItemTracking\WorkItemTracking\CustomControls\LookInFolders\". So if you want to store the .wicc and dll in some custom folder (eg c:\program files\MyTool\) you can, by adding this path as a value name under the above reg key.

2. Environment.SpecialFolder.CommonApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\10.0\

3. Environment.SpecialFolder.LocalApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\10.0\

4. PrivateAssemblies Folder (eg C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies)

5. Environment.SpecialFolder.CommonApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\

6. Environment.SpecialFolder.LocalApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\

Location 5, and 6 is a fall back that VS2010, 2008 and 2005 look under for custom control so we recommend not using those folders to keep the 2008 or 2010 version of the control. Ideally if you have VS2008 and 2010 side by side, you should drop the custom controls for 2008 in one of these folders:

1. Environment.SpecialFolder.CommonApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\9.0\

2. Environment.SpecialFolder.LocalApplicationData\Microsoft\Team Foundation\Work Item Tracking\Custom Controls\9.0\

 

Wicc File

This file tell us where the custom control is. The filename is the name of the control. For example if in the XML the contorlType is specific as MultiValueControl, we will look for MultiValueControl.wicc file in the custom controls folders.

 

Here is a typical content of a .wicc file:

 

 

<?xml version="1.0"?>

<CustomControl xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">

  <Assembly>WitCustomControlLibrary.dll</Assembly>

  <FullClassName>WitCustomControl.MultiValueControl</FullClassName>

</CustomControl>

 

 

The xml file basically says which assembly (can be full path path) and the FullClassName of the custom control.

 

Making it easier

We made some changes in 2010 that makes working with custom controls easier. Keep in mind these changes only applies to VS 2010, we may remove support for these in the next version in favor for a more sophisticated mechanism.

In the control definition, you can specify a PreferredType that will be used instead of the standard type if was installed on the client. Say you have an IdentityControl that you like to use it for the AssignedTo field. Here is how you define specify that in the form xml:

<Control Type="FieldControl" PreferredType=”IdentityControl” FieldName="System.AssigedTo" Label="Assigned To” LabelPosition="Left" />

Again, if a client doesn’t have IdentityControl deployed it will fall back to using the standard FieldControl. VS2008 client will just ignore the PreferredType and use the Type instead.

Comments

  • Anonymous
    November 17, 2010
    The Making it easier section is wrong. I used PreferredType attribute and tested it with both VS2008 and VS2010 (TFS 2010) and it was acting like I have specified the IdentityControl in Type attrib.

  • Anonymous
    November 22, 2010
    Is there any chance a checkbox control could be released for TFS workitem templates? Similiar to what worked in 2008: ukvsts.codeplex.com/wikipage

  • Anonymous
    December 15, 2010
    Greg I'm still confused about how to handle deploying custom work item controls for VS 2005, VS 2008, and VS2010. Is there a more detailed posting that explains in detail the exact steps needed for deployment of custom controls for multiple versions of VS?

  • Anonymous
    February 23, 2011
    hi, i am trying to upgrade existing controls to ref vs2010 assemblies and had many errors so I started a new project and added a ref to Microsoft.TeamFoundation.WorkItemTracking.Controls.dll from PrivateAssemblies.  Intellisence sees the types and implements the interface, but when i compile it says the type IWorkItemControl doesn't exist, which is the same error I received in the existing project. any help is appreciated.

  • Anonymous
    September 16, 2011
    Hi, I have a following scenario to be verified. In the Task work item when the 'State' field value changes from 'Active' to 'Closed', the 'Links' tab should have atleast one linked item.. Kinldy let me know how this can be achieved using custom control method or if any way is possible? Thanks & Regards, Sen

  • Anonymous
    August 29, 2012
    Does this still apply in 2012?  

  1.       All ValueNames under " HKEY_LOCAL_MACHINESOFTWAREMicrosoftVisualStudio10.0WorkItemTrackingWorkItemTrackingCustomControlsLookInFolders". So if you want to store the .wicc and dll in some custom folder (eg c:program filesMyTool) you can, by adding this path as a value name under the above reg key. I'm trying this with 11.0 and I'm getting nowhere.
  • Anonymous
    September 27, 2012
    I have the same question as Ryan. What is the search order for TFS2012? I can't find any of those folders with 11.0.

  • Anonymous
    October 23, 2012
    i am going through the same trouble as ryan and vahid.  did anyone get anywhere?

  • Anonymous
    June 04, 2014
    I know this is a fairly old article, but how would we apply this to VS Online TFS work items? Thanks!

  • Anonymous
    May 24, 2015
    Hi ! Can i use multiple WHEN conditions in WITD? Is it possible to use multiple conditions in single WHEN statement because i need to populate a field based on the two field values. My scenario is like this : I need to populate the field 'Priority' based on the values of 'Severity' && 'Likelihood' in TFS using WHEN condition in WITD. Help me out about this situation. Thanks in advance !