MSDN Magazin > Home > Ausgaben > 2007 > September >  Team System: Unterstützung für Arbeit...
Team System
Unterstützung für Arbeitsaufgaben und das Rückgängigmachen
Brian A. Randell

Codedownload verfügbar unter: TeamSystem2007_09.exe (197 KB)
Browse the Code Online
Im Artikel dieser Rubrik vom Januar 2007 (msdn.microsoft.com/msdnmag/issues/07/01/TeamSystem) habe ich beschrieben, wie ein Add-In für Microsoft® Word 2003 erstellt wird, das mit dem Versionskontrollsubsystem von Team Foundation Server zusammenarbeitet. Dann habe ich mich im Artikel vom April 2007 (msdn.microsoft.com/msdnmag/issues/07/04/TeamSystem) mit dem Subsystem der Arbeitsaufgabenverfolgung beschäftigt. Im Artikel dieses Monats erläutere ich, wie Sie dem Add-In Unterstützung für Arbeitsaufgaben hinzufügen können. Darüber hinaus erfahren Sie, wie Sie ein Feature hinzufügen, das in der ersten Version des Add-Ins hätte enthalten sein sollen – Unterstützung für das Rückgängigmachen.

Änderungen
Beim ersten Artikel, der sich mit dem Add-In beschäftigte, habe ich die Betaversion von Microsoft Visual Studio® 2005 Tools für 2007 Microsoft Office System (Visual Studio 2005 Tools für Office Second Edition oder kurz VSTO 2005 SE) verwendet. In der Zwischenzeit hat Microsoft die endgültige Version veröffentlicht, die die Erstellung von Anwendungs-Add-Ins sowohl für Office 2003 als auch für 2007 Office System unterstützt. Wenn Sie daher die in diesem Artikel beschriebenen Schritte nachvollziehen möchten, müssen Sie von der ersten „Version“ des Add-Ins auf die RTM-Version aktualisieren. Öffnen Sie hierzu einfach die Projektmappe, und führen Sie eine Neukompilierung auf einem Computer durch, auf dem VSTO 2005 SE installiert ist. Nachdem Sie sichergestellt haben, dass die neue Version funktioniert, besteht der nächste Schritt darin, Unterstützung für das Rückgängigmachen ausstehender Änderungen hinzuzufügen. Dieses Feature erfordert, dass Sie die tfsvcUtil-Klasse und die ThisAddin-Klasse ändern.
Fügen Sie in tfsvcUtil die neue freigegebene Methode „UndoPendingChanges“ hinzu, die den vollständigen Pfad zu dem Dokument akzeptiert, das gerade geändert wird, und lassen Sie sie einen booleschen Wert zurückgeben. Es stellt sich heraus, dass die Kernfunktionalität dieser neuen Methode die vorhandene CheckInDocument-Methode imitiert. Die Methode prüft, ob eine gültige Verbindung zu Team Foundation Server hergestellt und ein gültiger Arbeitsbereich geladen wurde. Nach Abschluss dieses Vorgangs ruft sie ein Array von PendingChanges-Objekten für das übergebene Dokument ab. Vorausgesetzt, dass eine ausstehende Änderung zurückgegeben wird, wird die Undo-Methode des Arbeitsbereichs des Benutzers aufgerufen, wobei das PendingChanges-Array übergeben wird. Diese Methode sollte den ganzzahligen Wert 1 zurückgeben. Ist dies der Fall, gibt die Methode „True“ zurück. Andernfalls wird tfsUtilException unter Verwendung der neu definierten Konstante MSG_UNDO_NOT_ZERO ausgelöst. Abbildung 1 zeigt die vollständige Methodenliste.
Public Shared Function UndoPendingChanges( _
  ByVal docPath As String) As Boolean
  If serverValidated Then
    If m_userWorkspace Is Nothing Then
      Dim userWorkstation As Workstation = Workstation.Current
      Dim docWSInfo As WorkspaceInfo = _
        userWorkstation.GetLocalWorkspaceInfo(docPath)
      m_userWorkspace = m_tfsVCS.GetWorkspace(docWSInfo)
    End If

    Dim pc As PendingChange() = _
      m_userWorkspace.GetPendingChanges(docPath)

    If pc IsNot Nothing AndAlso pc.Length > 0 Then
      Dim retval As Integer = m_userWorkspace.Undo(pc)
      ' Retval should equal the number of items 'undone'
      If retval = 1 Then
        Return True
      Else
        Throw New tfsUtilException(String.Format( _
          MSG_UNDO_NOT_ZERO, docPath, retval))
      End If
    Else
      Return False
    End If
  Else
    Throw New tfsUtilException(MSG_SERVER_NOT_VALIDATED)
  End If
End Function

Die Änderungen, die Sie an der ThisAddIn-Klasse vornehmen müssen, sind relativ unkompliziert. Wie zuvor gehe ich aus Platzgründen nicht allzu ausführlich auf den spezifischen Code des Word-Add-Ins ein. (Sie können den Download für diesen Artikel mit der vorherigen Version vergleichen, um die Änderungen zu sehen.) Natürlich müssen Sie die Klasse ändern, um der Symbolleiste die neue Schaltfläche „Ausstehende Änderungen rückgängig machen“ hinzuzufügen, sowie einen Click-Ereignishandler für die neue Schaltfläche und zusätzlichen Code für die Verarbeitung von Statusänderungen hinzufügen, um zu steuern, ob die Schaltfläche aktiviert ist. Im Wesentlichen sollte der aktivierte Status der Schaltfläche „Ausstehende Änderungen rückgängig machen“ dem der vorhandenen Schaltfläche „Einchecken“ entsprechen.

Unterstützung für Arbeitsaufgaben
Die Änderungen, die Sie durchführen müssen, um Unterstützung für die Zuordnung von Arbeitsaufgaben zu einem Eincheckvorgang hinzuzufügen, lassen sich in drei große Gruppen einteilen. Zuerst müssen Sie die tfsvcUtil-Klasse ändern, damit das Herstellen von Verbindungen zum Arbeitsaufgabenspeicher unterstützt wird. Dann müssen Sie die CheckInDocument-Methode ändern, damit die eigentliche Zuordnung der Arbeitsaufgaben vorgenommen wird. Abschließend müssen Sie das vorhandene frmCheckIn-Dialogfeld ändern, um die Auflistung von Arbeitsaufgaben zu unterstützen, die der Benutzer im Rahmen eines Eincheckvorgangs auswählen kann.
Um Arbeitsaufgaben zu programmieren, fügen Sie der Microsoft.TeamFoundation.WorkItemTracking.Client.dll-Assembly einen Verweis vom TFSUtil-Projekt hinzu. Wie bereits in früheren Artikeln erwähnt, werden die unterstützenden Assemblys von Team Explorer standardmäßig im globalen Assemblycache (GAC) installiert. Die Assemblys werden jedoch nicht vom Installationsprogramm für die Anzeige im Dialogfeld „Verweise hinzufügen“ von Visual Studio 2005 registriert. Sie müssen entweder Ihre Registrierung ändern, damit die Assemblys im Dialogfeld „Verweise hinzufügen“ angezeigt werden, oder manuell nach den Assemblys suchen. Sie finden die Assemblys unter %Programme%\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\.
Nachdem Sie den Verweis hinzugefügt haben, müssen Sie die tfsvcUtil-Klasse ändern und am Anfang der Quelldatei wie folgt eine Imports-Anweisung hinzufügen:
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Wenn das Add-In eine Verbindung zum Team Foundation Server-Feld herstellt, stellt es derzeit nur eine Verbindung zum Versionskontrolldienst her. Sie könnten die vorhandene Connect-Methode ändern, sodass auch eine Verbindung zum Arbeitsaufgabenspeicher hergestellt wird. Es kann jedoch Situationen geben, in denen der Benutzer des Add-Ins keine Arbeitsaufgaben zuordnet. Dadurch wäre die Connect-Methode dann mit unnötigem Aufwand verbunden. Stattdessen fügen Sie eine neue Methode hinzu, die getrennt aufgerufen wird, um eine Verbindung zum Arbeitsaufgabenspeicher herzustellen. Sie erstellen diese Methode als öffentliche Methode. In den meisten Fällen wird die Methode jedoch von vorhandenen Methoden aufgerufen, bevor Vorgänge im Zusammenhang mit Arbeitsaufgaben durchgeführt werden. Wenn die Verbindung zum Arbeitsaufgabenspeicher bereits vorhanden ist, wird sie gewissermaßen zu einer leeren Methode.
Sie müssen der tfsvcUtil-Klasse die neue freigegebene ConnectWIS-Methode hinzufügen. Diese Methode akzeptiert keine Parameter und gibt nichts zurück. Der Methodentext ist einfach. Zuerst wird geprüft, ob eine gültige Team Foundation Server-Instanz vorhanden ist. Ist das nicht der Fall, wird eine Ausnahme ausgelöst, da der Benutzer die Verbindung initiieren muss, bevor diese Methode aufgerufen wird. Andererseits könnten Sie die Architektur des Add-Ins ändern, um Anmeldeversuche bei der Team Foundation Server-Standardinstallation des Benutzers zu unterstützen. Wenn der Server verfügbar ist, wird mithilfe der GetServiceMethod der m_tfs-Instanz, die als TeamFoundationServer-Objekt typisiert ist, eine Verbindung zum Arbeitsaufgabenspeicher hergestellt:
Public Shared Sub ConnectWIS()
  If Not m_tfs Is Nothing Then
    If tfsvcUtil.m_tfsWIS Is Nothing Then
      tfsvcUtil.m_tfsWIS = CType( _
        m_tfs.GetService(GetType(WorkItemStore)), WorkItemStore)
    End If
  Else
    Throw New tfsUtilException(MSG_SERVER_NOT_VALIDATED)
  End If
End Sub
Sie werden feststellen, dass der Arbeitsaufgabenspeicher-Verweis in der Klassenvariablen „m_tfsWIS“ zwischengespeichert wird, die als WorkItemStore-Objekt typisiert ist. Sie müssen der Klasse diese Variable folgendermaßen hinzufügen:
Private Shared m_tfsWIS As WorkItemStore = Nothing
Nach Abschluss dieses Vorgangs müssen Sie eine überladene Version der CheckInDocument-Methode erstellen, die der vorhandenen Version bis auf einen zusätzlichen Eingabeparameter entspricht, der ein Array von WorkItemCheckinInfo-Instanzen akzeptiert. Schneiden Sie als Nächstes den Text aus der vorhandenen Methode aus, und fügen Sie ihn in Ihre neue Methode ein. Ändern Sie die ursprüngliche Methode so, dass sie die neue Version aufruft, und übergeben Sie „Nothing“ für das WorkItemCheckinInfo-Array. Die geänderte Version umfasst jetzt eine Codezeile:
Return tfsvcUtil.CheckInDocument(docPath, comment, Nothing)
Jetzt müssen Sie den Code in CheckInDocument ändern, um festzustellen, ob WorkItemCheckinInfo-Objekte an die Methode übergeben wurden. Wenn dies der Fall ist, ruft der Code die ConnectWIS-Methode auf, um sicherzustellen, dass eine Verbindung zum Arbeitsaufgabenspeicher hergestellt wurde. Nach Abschluss dieses Vorgangs rufen Sie die überladene Version von CheckIn auf, die ein Array von WorkItemCheckinInfo-Instanzen akzeptiert, und übergeben „Nothing“ für Eincheckhinweise und das Außerkraftsetzen von Richtlinien. Abbildung 2 zeigt die vollständige Liste.
Public Shared Function CheckInDocument( _
  ByVal docPath As String, ByVal comment As String, _
  ByVal SelectedWorkItems() As WorkItemCheckinInfo) _
  As Integer

  If serverValidated Then
    If m_userWorkspace Is Nothing Then
      Dim userWorkstation As Workstation = Workstation.Current
      Dim docWSInfo As WorkspaceInfo = _
        userWorkstation.GetLocalWorkspaceInfo(docPath)
      m_userWorkspace = m_tfsVCS.GetWorkspace(docWSInfo)
    End If

    Dim pc As PendingChange() = _
      m_userWorkspace.GetPendingChanges(docPath)

    If pc IsNot Nothing AndAlso pc.Length > 0 Then
      If SelectedWorkItems IsNot Nothing _
        AndAlso SelectedWorkItems.Length > 0 Then

        tfsvcUtil.ConnectWIS()

        Return m_userWorkspace.CheckIn( _
           pc, comment, Nothing, SelectedWorkItems, Nothing)
       Else
         Return m_userWorkspace.CheckIn(pc, comment)
      End If
    Else
      Return -1
    End If
  Else
    Throw New tfsUtilException(MSG_SERVER_NOT_VALIDATED)
  End If
End Function


Zurückgeben von Arbeitsaufgabenabfragen
Sie haben dem Eincheckprozess jetzt Unterstützung für die Zuordnung von Arbeitsaufgaben hinzugefügt. Sie müssen jedoch die tfsvcUtil-Klasse erweitern, um die Rückgabe einer Liste von Arbeitsaufgabenabfragen für das aktuelle Teamprojekt zu unterstützen. Außerdem benötigen Sie eine Methode, die eine Abfrage ausführt und die Arbeitsaufgaben an den Aufrufer zurückgibt, damit sie für den Benutzer im Rahmen des integrierten Eincheckverfahrens angezeigt werden können.
Hierzu fügen Sie zwei Methoden hinzu. Die erste Methode, GetWIQ, gibt ein StoredQueriesCollection-Objekt zurück. Die zweite Methode, RunWIQ, akzeptiert einen Abfragenamen als Zeichenfolgenparameter und gibt ein WorkItemsCollection-Objekt zurück. Ich habe das entsprechende Verfahren in der Aprilausgabe 2007 dieses Artikels beschrieben (msdn.microsoft.com/msdnmag/issues/07/04/TeamSystem). Abbildung 3 zeigt den erforderlichen Code.
Public Shared Function GetStoredQueries(ByVal docPath As String) _
  As StoredQueryCollection

  If IsServerReady Then
    tfsvcUtil.ConnectWIS()

    If m_userWorkspace Is Nothing Then
      Dim userWorkstation As Workstation = Workstation.Current
      Dim docWSInfo As WorkspaceInfo = _
        userWorkstation.GetLocalWorkspaceInfo(docPath)
      m_userWorkspace = m_tfsVCS.GetWorkspace(docWSInfo)
    End If

    Dim vcTeamProject As TeamProject = _
      m_userWorkspace.GetTeamProjectForLocalPath(docPath)

    m_wisProject = m_tfsWIS.Projects(vcTeamProject.Name)

    Return m_wisProject.StoredQueries()
  Else
    Throw New tfsUtilException(MSG_SERVER_NOT_VALIDATED)
  End If
End Function

Public Shared Function RunWIQ(ByVal docPath As String, _
  ByVal WIQ As StoredQuery) As WorkItemCollection

  Dim wiqlToExecute As String = WIQ.QueryText.ToLower()
  Dim params As Hashtable = Nothing
  Dim wic As WorkItemCollection = Nothing

  If wiqlToExecute.Contains(MACRO_PROJECT) Then
    If params Is Nothing Then
      params = New Hashtable
    End If
    params.Add(MACRO_PROJECT.Substring(1), WIQ.Project.Name)
  End If
  If wiqlToExecute.Contains(MACRO_ME) Then
    If params Is Nothing Then params = New Hashtable
    params.Add(MACRO_ME.Substring(1), _
      m_tfsVCS.AuthenticatedUser.Substring( _
      m_tfsVCS.AuthenticatedUser.IndexOf("\"c) + 1))
  End If

  If params IsNot Nothing Then
    wic = m_tfsWIS.Query(wiqlToExecute, params)
  Else
    wic = m_tfsWIS.Query(wiqlToExecute)
  End If

  If wic.Count = 0 Then
    Return Nothing
  Else
    Return wic
  End If
End Function


Aktualisieren des Eincheckdialogfelds
Sie haben nun den Hauptcode für die Zuordnung von Arbeitsaufgaben beim Einchecken geschrieben. Jetzt müssen Sie das vorhandene Eincheckdialogfeld ändern, sodass es die Zuordnung von Arbeitsaufgaben unterstützt. Vergrößern Sie zunächst das vorhandene Formular, indem Sie die Größeneigenschaft auf etwa 640 × 480 setzen, damit Sie ausreichend Platz zum Anpassen des Layouts haben. Fügen Sie als Nächstes dem Formular ein Bereichssteuerelement hinzu, und geben Sie ihm den Namen „pnlComments“. Schneiden Sie dann das vorhandene txtComment-Textfeld aus dem Formular aus, fügen Sie es in den neuen Bereich ein, und setzen Sie die Dock-Eigenschaft auf „Fill“. Sie müssen dem txtComment_TextChanged-Ereignishandler erneut eine Handles-Klausel hinzufügen, da die vorhandene Klausel beim Ausschneiden des Textfelds entfernt wird.
Dem Formular muss auf der linken Seite ein GroupBox-Steuerelement namens „grpOptions“ hinzugefügt werden. Fügen Sie im Gruppenfeld zwei RadioButton-Steuerelemente hinzu, und nennen Sie sie „rdoComments“ und „rdoWorkItems“. Ändern Sie ihre AutoSize-Eigenschaft in „False“ und ihre Appearance-Eigenschaft in „Button“. Setzen Sie die Checked-Eigenschaft des Optionsfelds „rdoComments“ auf „True“. Ordnen Sie abschließend die Elemente im Formular neu an, sodass es Abbildung 4 ähnelt.
Abbildung 4 Geändertes Eincheckdialogfeld mit Kommentarseite (Klicken Sie zum Vergrößern auf das Bild)
Nachdem Sie nun die grundlegenden Änderungen an der Benutzeroberfläche vorgenommen haben, müssen Sie Unterstützung für das Anzeigen von Arbeitsaufgaben in einem Raster, wenn auf die Umschaltfläche „Arbeitsaufgaben“ geklickt wird, hinzufügen. Fügen Sie dem Formular ein Bereichssteuerelement namens „pnlWorkItems“ hinzu. Fügen Sie innerhalb dieses Bereichs zwei weitere Bereiche hinzu: PnlSQCombo und pnlGridHolder. Setzen Sie die Dock-Eigenschaft von pnlSQCombo auf „Top“ und von pnlGridHolder auf „Fill“. Sie müssen dann pnlSQCombo eine Bezeichnung und ein Kombinationsfeld-Steuerelement sowie pnlGridHolder ein DataGridView-Steuerelement hinzufügen. Nennen Sie das Kombinationsfeld „cboStoredQueries“ und das Raster „dgvWorkItems“. Docken Sie das Raster innerhalb des Bereichssteuerelements mithilfe des Smarttags an. Passen Sie die Größe und die Position von pnlWorkItems so an, dass sie pnlComments entsprechen, und setzen Sie seine Visible-Eigenschaft auf „False“.
Wenn der Benutzer auf die Umschaltfläche „Arbeitsaufgaben“ klickt, führt der Click-Ereignishandler die erforderlichen Schritte durch, um die Arbeitsaufgaben verfügbar zu machen. Es ist nicht sinnvoll, dem Formular den Mehraufwand zur Ladezeit hinzuzufügen – es sei denn, Sie wissen, dass Sie beim Einchecken eines Dokuments immer Arbeitsaufgaben zuordnen möchten. Zur Durchführung der erforderlichen Vorgänge ist recht viel Code erforderlich, bei dem es sich zumeist um allgemeinen Windows® Forms-Code handelt, der benötigt wird, um die Benutzeroberfläche korrekt einzustellen.
Beim Klicken auf die Umschaltfläche „Arbeitsaufgaben“ werden nacheinander die folgenden Vorgänge durchgeführt: Laden der Datenquellen des Kombinationsfelds für die Eincheckaktion, Definieren der Spalten des Rasters, Laden der gespeicherten Abfragen, Ausführen der Abfrage „Eigene Arbeitsaufgaben“ und Binden der Ergebnisse der Abfrage an das Rastersteuerelement. Abbildung 5 zeigt den Code, der aufgerufen wird, wenn der Benutzer auf die Umschaltfläche „Arbeitsaufgaben“ klickt.
Private Sub rdoWorkItems_Click(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles rdoWorkItems.Click
  ' Load ComboBox Data Sources
  LoadCheckInActionComboBox()

  ' Define Grid Layout
  DefineWorkItemGrid()

  ' Load WIQs
  LoadStoredQueries()
  For Each sq As StoredQuery In msq
    If sq.Name = "My Work Items" Then
      Me.cboStoredQueries.SelectedItem = sq
      Exit For
    End If
  Next

  ' Run WIQ
  LoadGridData()

  Me.pnlComments.Visible = False
  Me.pnlWorkItems.Visible = True
End Sub

Der rdoWorkItems_Click-Ereignishandler ruft zur Durchführung seiner Aufgaben eine Reihe unterstützender Prozeduren auf. LoadCheckInActionComboBox initialisiert die Datenquellen für das Eincheckaktions-Kombinationsfeld, das im Raster angezeigt werden soll. Wenn Sie das Microsoft-Eincheckdialogfeld betrachten, werden Sie feststellen, dass im Kombinationsfeld für die Eincheckaktion je nach Art der ausgewählten Arbeitsaufgabe entweder nur „Zuordnen“ angezeigt wird oder dass „Zuordnen“ und „Auflösen“ angezeigt werden. Zum Imitieren dieses Verhaltens sind im Formular einige Vorgänge im Hintergrund erforderlich.
Um dies zu erreichen, müssen Sie zuerst zwei Klassenarrays definieren:
Private listAssociate(0) As String
Private listAssociateResolve(1) As String
Als Nächstes tauschen Sie in Abhängigkeit von der Art der ausgewählten Arbeitsaufgabe die Datenquelle des Kombinationsfelds für die Eincheckaktion zwischen diesen beiden Arrays aus. LoadCheckInActionComboBox lädt die Zeichenfolgenwerte in die Arrays.
Der Ereignishandler führt dann DefineWorkItemGrid aus, um das Rastersteuerelement zu initialisieren. Diese Methode fügt ein ungebundenes Kontrollkästchen-Steuerelement, vier datengebundene Textspalten (Arbeitsaufgabentyp, Arbeitsaufgaben-ID, Titel und Status) und ein ungebundenes Kombinationsfeld-Steuerelement für die Eincheckaktion hinzu. Als Nächstes wird LoadStoredQueries von rdoWorkItems_Click aufgerufen. Diese Methode ruft die zuvor erstellte GetStoredQueries-Methode auf. Dann erstellt sie eine Datenbindung zwischen den Ergebnissen und dem Kombinationsfeld-Steuerelement cboStoredQueries.
In der rdoWorkItems_Click-Methode durchläuft der Code die Liste gespeicherter Abfragen, bis er die Abfrage „Eigene Arbeitsaufgaben“ findet. Sobald er diese gefunden hat, legt der Code sie als derzeit ausgewählte Abfrage im Kombinationsfeld-Steuerelement „cboStoredQueries“ fest. Dann führt die Methode LoadGridData aus. Dadurch werden die Arbeitsaufgaben abgerufen, die von der Abfrage „Eigene Arbeitsaufgaben“ zurückgegeben wurden, und die Ergebnisse werden an das Raster gebunden. Zuletzt blendet rdoWorkItems_Click den Kommentarbereich aus und zeigt den Arbeitsaufgabenbereich an.
Damit das Raster auf ähnliche Weise wie die Microsoft-Version funktioniert, müssen Sie Ereignishandler für zwei rasterbezogene Ereignisse programmieren. Das erste Ereignis ist CellFormatting. Eine der im Raster angezeigten Spalten ist die Type-Eigenschaft aus dem WorkItem-Objekt. Diese Eigenschaft ist als WorkItemType-Objekt typisiert. Sie möchten die Name-Eigenschaft dieses Objekts im Raster anzeigen. Wenn die ToString-Methode ausgeführt wird, gibt das Objekt jedoch seinen vollqualifizierten Typnamen und nicht seine Name-Eigenschaft zurück. Um die Name-Eigenschaft anzuzeigen, müssen Sie den Wert der Zelle im CellFormatting-Ereignishandler ändern. Dieser Code prüft, ob die zu formatierende Spalte die Spalte „Arbeitsaufgabentyp“ ist:
Private Sub dgvWorkItems_CellFormatting(ByVal sender As Object, _
  ByVal e As DataGridViewCellFormattingEventArgs) _
  Handles dgvWorkItems.CellFormatting

  If e.ColumnIndex = typeColumnIndex Then
    If e.Value IsNot Nothing Then
      Dim wit As WorkItemType = CType(e.Value, WorkItemType)
      e.Value = wit.Name
      e.FormattingApplied = True
    End If
  End If
End Sub
Wenn dies der Fall und der Wert der Zelle kein Nullwert ist, ruft der Code die WorkItemType-Instanz aus der Zelle ab und ändert den Wert der Zelle in den Wert der Name-Eigenschaft.
Als Nächstes müssen Sie einen Ereignishandler für das Current-CellDirtyStateChanged-Ereignis implementieren. In diesem Handler ändern Sie die Datenquelle des Kombinationsfelds für die Eincheckaktion basierend auf dem Typ der ausgewählten Arbeitsaufgabe. Schreiben Sie den Code so, dass er nur ausgeführt wird, wenn sich der Status der Spalte mit dem Kontrollkästchen ändert.
Um festzustellen, welche Datenquelle verwendet werden sollte, müssen Sie auf das WorkItem-Objekt zugreifen, das an die aktuelle Zeile gebunden ist. Dann rufen Sie seine GetNextState-Methode auf und übergeben den Zeichenfolgenwert „Microsoft.VSTS.Actions.Checkin“. Der Code prüft, ob ein gültiger Statusübergang von einem Eincheckvorgang vorliegt. Ist dies der Fall, empfängt der Code eine gültige Zeichenfolge, die ihm mitteilt, dass im Kombinationsfeld sowohl „Zuordnen“ als auch „Auflösen“ angezeigt werden sollte. Wenn keine gültige Zeichenfolge abgerufen wird, sollte nur „Zuordnen“ verfügbar sein. Auf diese Weise legt der Code die richtige Datenquelle fest und führt dann ein Commit für den aktuellen Bearbeitungsvorgang aus, wodurch sich der Status des Kontrollkästchens ändert.
Der Code prüft dann den Wert des Kontrollkästchens. Wenn es aktiviert (auf „True“ gesetzt) wurde, wird das Kombinationsfeld für die Eincheckaktion aktiviert und zum aktiven Steuerelement, und ein Bearbeitungsvorgang wird gestartet. Wenn das Kontrollkästchen deaktiviert wird, setzt der Code das Kombinationsfeld zurück. Abbildung 6 zeigt die Details.
Private Sub dgvWorkItems_CurrentCellDirtyStateChanged( _
  ByVal sender As Object, ByVal e As System.EventArgs) _
  Handles dgvWorkItems.CurrentCellDirtyStateChanged

  Dim c As DataGridViewCell = dgvWorkItems.CurrentCell

  If c.ColumnIndex = checkedColumnIndex Then
    Dim dcb As DataGridViewComboBoxCell = _
      CType(dgvWorkItems(comboBoxColumnIndex, _
      c.RowIndex), DataGridViewComboBoxCell)

    Dim currentRow As DataGridViewRow = dgvWorkItems.Rows(c.RowIndex)
    Dim wi As WorkItem = CType(currentRow.DataBoundItem, WorkItem)

    Dim nextState As String = _
      wi.GetNextState("Microsoft.VSTS.Actions.Checkin")

    If String.IsNullOrEmpty(nextState) Then
      dcb.DataSource = listAssociate
    Else
      dcb.DataSource = listAssociateResolve
    End If

    dgvWorkItems.CommitEdit( _
      DataGridViewDataErrorContexts.CurrentCellChange)

    If CBool(c.Value) Then
      dcb.ReadOnly = False
      dcb.Value = dcb.Items.Item(0)

      dgvWorkItems.CurrentCell = dcb
      dgvWorkItems.BeginEdit(True)
    Else
      dcb.Value = Nothing
      dcb.ReadOnly = True
    End If
  End If
End Sub

Der letzte Code, den Sie zum Verarbeiten von Arbeitsaufgaben hinzufügen müssen, wird durch Erstellen eines Arrays von WorkItemCheckinInfo-Objekten im FormClosing-Ereignis entwickelt (siehe Abbildung 7). Sie erstellen dieses Array, indem Sie die Zeilen des Rasters durchlaufen und eine WorkItemCheckinInfo-Instanz erstellen, wenn in der Spalte das Kontrollkästchen aktiviert wird. Wenn Sie eine WorkItemCheckinInfo-Instanz erstellen, geben Sie die Eincheckaktion an. Neben dieser Methode müssen Sie dem Formular eine öffentliche Eigenschaft – WorkItems – hinzufügen, damit das Array abgerufen werden kann, sobald das Dialogfeld geschlossen wird. Sie legen diese Eigenschaft am Ende der FormClosing-Methode fest.
Private Sub frmCheckIn_FormClosing( _
  ByVal sender As Object, ByVal e As FormClosingEventArgs) _
  Handles Me.FormClosing

  Dim chkCol As DataGridViewCell
  Dim cboCol As DataGridViewCell

  Dim wiciList As New List(Of WorkItemCheckinInfo)
  Dim cia As WorkItemCheckinAction = WorkItemCheckinAction.None

  For Each row As DataGridViewRow In Me.dgvWorkItems.Rows
    chkCol = row.Cells(checkedColumnIndex)
    If CBool(chkCol.Value) Then
      ' Item is selected
      cboCol = row.Cells(comboBoxColumnIndex)
      Select Case cboCol.Value.ToString()
        Case "Associate"
          cia = WorkItemCheckinAction.Associate
        Case "Resolve"
          cia = WorkItemCheckinAction.Resolve
        Case Else
          cia = WorkItemCheckinAction.None
      End Select

      wiciList.Add(New WorkItemCheckinInfo( _
        CType(row.DataBoundItem, WorkItem), cia))
    End If
  Next

  If wiciList.Count > 0 Then
    Me.WorkItems = wiciList.ToArray()
  Else
    Me.WorkItems = Nothing
  End If
End Sub


Abschließende Details
Sie finden im Formular zusätzlichen Code für die Verarbeitung des SelectedValueChanged-Ereignisses des Kombinationsfelds mit den gespeicherten Abfragen. Der letzte Schritt, der erforderlich ist, damit das Add-In Arbeitsaufgaben unterstützt, besteht darin, die cbbCheckInDoc_Click-Methode der ThisAddIn-Klasse im Word-Add-In zu ändern. Mit der geänderten Version wird einfach geprüft, ob die neue WorkItems-Eigenschaft des Dialogfelds Daten aufweist. Ist dies der Fall, wird die neue Version der CheckInDocument-Methode aufgerufen. Andernfalls wird die alte Version ausgeführt. Abbildung 8 zeigt das abgeschlossene Eincheckdialogfeld in Verbindung mit Arbeitsaufgaben.
Abbildung 8 Abgeschlossenes Eincheckdialogfeld mit Unterstützung für Arbeitsaufgaben (Klicken Sie zum Vergrößern auf das Bild)
Wenn Sie jetzt das Add-In ausführen, können Sie der Quellcodeverwaltung ein Dokument hinzufügen, es mit Kommentaren einchecken und Arbeitsaufgaben zuordnen, es auschecken und sogar ausstehende Änderungen rückgängig machen. An diesem Punkt haben Sie bereits viel erreicht, aber es gibt noch zahlreiche weitere Möglichkeiten. In der nächsten Ausgabe dieser Rubrik werde ich mich mit dem Hinzufügen von Eincheckhinweisen, Richtlinienunterstützung und möglicherweise noch mit weiteren interessanten Features befassen.

Senden Sie Ihre Fragen und Kommentare (in englischer Sprache) an mmvsts@microsoft.com.


Brian A. Randell ist leitender Berater bei MCW Technologies LLC. Brian Randell hält Vorträge, unterrichtet und schreibt über Microsoft-Technologien. Er ist Autor des Pluralsight-Kurses „Applied Team System“ und Microsoft MVP. Sie erreichen Brian Randell über seinen Blog unter mcwtech.com/cs/blogs/brianr.

Page view tracker