Using rich HTML descriptions instead of plain text
Objective
Allow rich HTML formatting in description fields of the MSF Agile process template.
Note: The MSF CMMI process does support HTML formatting by default. In order to use it you have to enable the formatting toolbar (see Step 6 below).
Work Item Customization
Step 1: Add a new HTML description field
Since the System.Description field is defined of type string as opposed to type HTML we need to create a new field:
Step 2: Change the work item layout
Use your own HTML field instead of System.Description
Step 3: Refresh Work Item cache
Right-click "Work Items" in Team Explorer and select "Refresh".
Step 4: Enable the formatting toolbar
Right-click on the Visual Studio toolbar, find and click "Formatting":
A new toolbar will appear:
Result
Click into the description field and use the toolbar to format your input:

Optional Step 5: Copying the old descriptions to the new HTML field
It would be a pity to loose the existing descriptions so let's write a small utility using the Team Foundation Object model to copy the "old" descriptions to the new HTML field:
static void CopyOldDescriptions()
{
// TODO: Change these values:
string tfsName = "servertogo";
string tfsProjectName = "WorkItemCustomization";
string tfsHtmlDescriptionFieldName = "DescriptionHtml";
string tfsWorkItemType = "Task";
using (TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsName))
{
WorkItemStore wit = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
WorkItemCollection result = wit.Query(String.Format("SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '{0}' AND [System.WorkItemType] = '{1}'", tfsProjectName, tfsWorkItemType));
List<WorkItem> affectedWorkItems = new List<WorkItem>();
foreach (WorkItem wi in result)
{
if (wi.Description.Length > 0)
{
// Set new description
string value = (string)wi[tfsHtmlDescriptionFieldName];
if (String.IsNullOrEmpty(value))
{
wi[tfsHtmlDescriptionFieldName] = wi.Description.Replace("\n", "<br>");
}
else
{
wi[tfsHtmlDescriptionFieldName] += "<br><p>Old description:</p><p>" + wi.Description.Replace("\n", "<br>") + "</p>";
}
// Delete old description
wi.Description = String.Empty;
affectedWorkItems.Add(wi);
}
}
if (affectedWorkItems.Count > 0)
{
wit.BatchSave(affectedWorkItems.ToArray());
MessageBox.Show("Items updated: " + affectedWorkItems.Count);
}
else
{
MessageBox.Show("Nothing to do.");
}
}
}
Happy formatting. :-)