はい、できます。TFS ワークアイテムはカスタマイズ可能です。私がこのバージョンで望むほどではありませんが、やりたいことはできます。
次のフィールド定義で試してみましょう。Notes Date と Notes Author は読み取り専用で、システムからデフォルト値を取得します。Notes フィールドは HTML であり、そこには何でも入れることができます。これは、TFS プロセス エディターで行うことができます。
<FIELD reportable="dimension" type="DateTime" name="Notes Date" refname="System.VSTS.Notes.Date">
<DEFAULT from="clock" />
<READONLY not="[Global]\Team Foundation Administrators" />
</FIELD>
<FIELD reportable="dimension" type="String" name="Notes Author" refname="System.VSTS.Notes.Author">
<DEFAULT from="currentuser" />
<READONLY not="[Global]\Team Foundation Administrators" />
</FIELD>
<FIELD type="HTML" name="Notes" refname="System.VSTS.Notes" />
</FIELDS>
もちろん、フォームにコントロールを追加する必要があります。
もう 1 つ試すことができるのは、Notes フィールドのみを保持して WorkItemChanged イベントに登録し、Web サービスを作成して Notes フィールドを Date と Author で更新することです。Changed BY および Changed Date フィールドは、この情報を提供します。Brian A. Randell - Team Foundation System Event Serviceによるこの記事で、利用可能なイベントとそれらをサブスクライブする方法について学ぶことができます。
[WebService(Namespace = "http://mynamespace.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class UpdateWorkItem : System.Web.Services.WebService
{
private static TeamFoundationServer _Tfs;
private static WorkItemStore _WorkItemStore;
private static List<WorkItem> _ChangedWorkItems = new List<WorkItem>();
[SoapDocumentMethod(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify", RequestNamespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
[WebMethod]
public void Notify(string eventXml, string tfsIdentityXml)
{
EventLog.WriteEntry("TFS Services", "Log Started: Notify Webmethod");
// Load the recieved XML into a XMLDocument
XmlDocument eventXmlDoc = new XmlDocument();
eventXmlDoc.LoadXml(eventXml);
XmlElement eventData = eventXmlDoc.DocumentElement;
// Validate event data
if (eventData != null)
{
// Get Work Item id from event data
int id = GetWorkItemId(eventData);
//EventLog.WriteEntry("TFS Services", String.Format("eventXmlDoc {0}", eventXmlDoc.InnerXml));
EventLog.WriteEntry("TFS Services", String.Format("Got Id {0}", id));
string changedby = GetWorkItemChangedBy(eventData);
EventLog.WriteEntry("TFS Services", String.Format("Got changedby {0}", changedby));
if (changedby != "TFSSERVICE")
{
//Add a 15 second delay in order to make sure all workitems are saved first before starting to update them
Thread.Sleep(15000);
EventLog.WriteEntry("TFS Services", "Calling UpdateWorkItemInternal");
UpdateWorkItemInternal(id);
}
}
}
private int GetWorkItemId(XmlElement eventData)
{
return Convert.ToInt32(eventData.SelectSingleNode("CoreFields/IntegerFields/Field[ReferenceName='System.Id']/NewValue").InnerText);
}
private string GetWorkItemChangedBy(XmlElement eventData)
{
return Convert.ToString(eventData.SelectSingleNode("CoreFields/StringFields/Field[ReferenceName='System.ChangedBy']/NewValue").InnerText);
}
private static void UpdateWorkItemInternal(int id)
{
//Connect To TFS Server
EventLog.WriteEntry("TFS Services", string.Format("Updating Work Item {0}", id));
_Tfs = TeamFoundationServerFactory.GetServer("TeamServer");
_WorkItemStore = (WorkItemStore)_Tfs.GetService(typeof(WorkItemStore));
WorkItem workItem = _WorkItemStore.GetWorkItem(id);
switch ((string)workItem.Fields["System.WorkItemType"].Value)
{
case "Bug":
UpdateNotes(workItem);
break;
default:
break;
}
foreach (WorkItem item in _ChangedWorkItems)
{
if (item.IsDirty)
{
foreach (Field field in item.Fields)
{
if (!field.IsValid)
{
Console.Write("Not valid");
}
}
EventLog.WriteEntry("TFS Services", string.Format("Saving WorkItem: {0}", item.Id));
try
{
item.Save();
}
catch (Exception ex)
{
}
}
}
_ChangedWorkItems.Clear();
}
private static void UpdateNotes(WorkItem workItem)
{
Field notes = workitem.Fields["System.VSTS.Notes"];
if (notes != null)
{
notes = string.Format("{0} - {1}", workItem.ChangedDate, workItem.ChangedBy);
}
if (workItem.IsDirty)
{
if (!_ChangedWorkItems.Contains(workItem))
{
_ChangedWorkItems.Add(workItem);
}
}
}
}
これは、既存のコードからのコピーと貼り付けで簡単に汚れているため、タイプミスが発生していないことを確認するために慎重に確認してください。