What is custom control feature?

 

Now you can show your own controls in work item form. See for http://blogs.msdn.com/narend/archive/2006/09/27/773025.aspx introduction to this feature. This is part of SP1 beta . There is also a codeplex project to build & share generic controls.

 

Note: if you are trying to port VS2005 custom controls to Orcas see here

 

Where to get documentation & Sample of this control?

 

Apparently the SP1 beta comes with minimal documentation and we are working to deliver detailed documentation. See http://blogs.msdn.com/vstsue/archive/2006/09/27/777554.aspx for additonal documentation. The purpose of this entry is to enable quick start on using this feature. I attached a sample in this post and this sample (revised) will also be available in official documentation soon, and that documentation will give more details on this feature. See here for shorter documentation on this and another tiny sample.

 

High level overview on how custom controls work:

 

When work item form is drawn, the control names are read from the work item type xml. A custom control can be added in that work item type xml under form section like below for sample control:

 

                <Control Type="WorkItemIdReference" FieldName="MyFields.DuplicateId" Label="&amp;Duplicate Id:" LabelPosition="Left" CustomAttribute1="Custom parameters here" CustomAttribute2="Custom parameters here"/>

 

If it is built-in control, then it is loaded from product assembly. Otherwise, a file with name <ControlName>.wicc is searched in local disc in order described below. If a file is found, it is expected to be in below example format:

 

<?xml version="1.0"?>

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

  <Assembly>WitCustomControlSample.dll</Assembly>

  <FullClassName>WitCustomControlSample.WorkItemIdReference</FullClassName>

</CustomControl>

 

The xml file basically says which assembly (optionally with its path) and which class name implements the custom control. The control needs to implement at least IWorkItemControl interface (explained below). Why use the file instead of registry or other options? It enables xcopy deployment and is similar to add-ins deployment. The assembly is then loaded and an object of the specified type is created with an empty constructor and loaded into the form. If searched file is not found, then a control is shown there with an error message for troubleshooting.

 

Now that 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.

 

Custom control Search Order:

 

Custom controls are searched in folder “Microsoft\Team Foundation\Work Item Tracking\Custom Controls” under Environment.SpecialFolder.CommonApplicationData folder first, then under Environment.SpecialFolder.LocalApplicationData. For Orcas, search is first made under "9.0" folder under above directory. This enables installing both VS2005 and Orcas version of controls in same machine. See here for more information on this.

 

Creating custom control:

 

Custom controls need to derive from Control. Typically custom controls are built from UserControl. To create a new user control project, go to Visual Studio, File/new project and choose “Windows Control Library” to create a user control.

 

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 "<drive>:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies". Add reference to that assembly and line "using Microsoft.TeamFoundation.WorkItemTracking.Controls;" in code.  Below is definition of IWorkItemControl and comments on members in order of importance as I see it:

 

    public interface IWorkItemControl

    {

        bool ReadOnly { get; set; }

        string WorkItemFieldName { get; set; }

        object WorkItemDatasource { get; set; }

        StringDictionary Properties { get; set; }

        void Clear();

        void InvalidateDatasource();

        void FlushToDatasource();

        void SetSite(IServiceProvider serviceProvider);

        event EventHandler BeforeUpdateDatasource;

        event EventHandler AfterUpdateDatasource;

    }

 

WorkItemDatasource

This passes reference to source work item object. Cast this object to WorkItem type.

WorkItemFieldName

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.

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 Document service or VS Services. If services are not needed, do nothing in this method.

Clear

Control is asked to clear its contents

Properties

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.

BeforeUpdateDatasource

AfterUpdateDatasource

Raise these events before and 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

ReadOnly

Tells the control to display in readonly mode.

FlushToDatasource

 

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.

 

 

For additional functionality, below interfaces can be implemented optionally. I will talk about these interfaces may be in another post. It should be easy to figure out their usage by looking into their definition.

 

IWorkItemToolTip

IWorkItemUserAction

IWorkItemClipboard

See here for communicating with other controls 

 

Custom operations before and after save events:

 

If you need to perform certain operations before the workitem is attempted to be saved (with an option to abort save operation), or after workitem save, use the addin interfaces and hook to Saving & Saved events. You need to build an addin to do it if this has to work for both new and existing items. If this is for existing items, then you can do without Addin: Basically get document service by using GetService call of IServiceProvider passed to you and use FindDocument with workitemid to get curent document and hook to workitemsaved event. Addin interfaces are documented at http://blogs.msdn.com/narend/archive/2006/07/07/AccessingWitFromAddin.aspx .  FlushToDatasource described above is closest to do some operations just before save operation or when leaving the form.

 

About the attached sample

 

A sample is attached to this post (see end of post for attachments link). Check out the sample to see example implementation of IWorkItemControl members. The sample shows a control to accept a work item id and provides a button to navigate to that item. Steps to use the control is described here. The navigate part is example of using Work Item Tracking document service to manipulate WIT documents in VS. Now that you got work item object reference and the field name, implement the richness in your control as you desire. Build the control as dll and the custom control is ready.

 

Testing the custom control:

 

To test the control, create a .wicc file and see above for its format. You can copy the one in sample to start with and rename it to use your control’s name. Now edit the work item type xml. You might want to export an existing workitem’s xml using WitExport utility or use the one in the attached sample. Add a line like below in the xml.

 

<Control Type="WorkItemIdReference" FieldName="MyFields.DuplicateId" Label="&amp;Duplicate Id:" LabelPosition="Left" />

 

Place the wicc file in folders as explained in search order above. Open the work item form and you should see the control in action. Not seeing the control? See troubleshooting section below for help in debugging.

 

Deploying custom control:

 

The control is developed and tested. Now the wicc file and assembly needs to be deployed in boxes for all users. Two ways to deploy it:

-          xcopy deploy: Simply ask users to copy these two files to their local folders

-          Create setup package: A simple setup package can be created using VS setup project. Steps below:

o        In VS, right click on solution and add new project. Choose Other project type/setup and deployment in left pane of “Add Project” dialog, and choose “Setup project”

o        Right click on setup project and add output from controls project.

o        File system folders are shown by default. Add the folders, wicc files and assembly there. Build it for the setup msi. Share the msi for users to install.

 

Users also need to install SP1 to see controls. We know the deployment story is less than ideal and are investigating better deployment model.

 

Troubleshooting custom control issues:

 

-          Issue: Control is deployed, but work item form shows an error box there: This means that work item form failed to find the control assembly or failed to load it. The error on the errorbox should point to .net error. If the wicc file or assembly is not found, I recommend using FileMon tool from here, and using fusion logg viewer to find out where workitemform was looking for files and why it failed to load.

 

      Another reason users have trouble is when xml elements in wicc file differ by case or spelling - they need to be exact for deserialization to work. Also, pls remember that the end users must have SP1 beta installed for them to view the deployed controls.

 

      See how Mickey Gousset got this to work & issues faced here. Still no luck? Post your question with error you get in work item tracking forum 

 

-          How to debug code in custom control itself? : The control is loaded in visual studio, and it can be debugged using another visual studio instance or CLR debugger. To make sure symbols get loaded for debugging, deploy pdb files alone with dll. Attach the VS install by “Debug/Attach to Process” menu. Make sure symbols for control are loaded by “Debug/windows/modules” menu.

 

Got Ideas for generic custom controls?: 

Please share your ideas in codeplex opensource dev project: http://www.codeplex.com/WitCustomControls 

 

Got questions?:

 

Please raise your questions in workitemtracking forum: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=479&SiteID=1

         

 

<%//This posting is provided "AS IS" with no warranties of any kind and confers no rights.  Use of samples included in this posting is subject to the terms specified at http://www.microsoft.com/info/cpyright.htm %>