/// <summary> /// Refreshes the work items in the document. /// </summary> /// <remarks> /// <para>Deletes work items that are no longer returned, adds work items that are now returned, and re-orders work items that have changed position in query results.</para> /// <para>This call will also update the rich text content controls which are not bound to the Custom XML Parts.</para> /// </remarks> /// <param name="refreshData">The data needed for a refresh.</param> /// <param name="bookmarkNamingFunction">A function to return the bookmark to use for the given work item, first parameter is query index, second is work item id.</param> /// <param name="cancellationToken">Used to cancel the refresh.</param> public void RefreshWorkItems(FormatterRefreshData refreshData, Func <int, int, string> bookmarkNamingFunction, CancellationToken cancellationToken) { if (refreshData == null) { throw new ArgumentNullException("refreshData"); } Debug.Assert(refreshData.QueryWorkItemsBefore.Count() == refreshData.QueryWorkItemsAfter.Count(), "Before and after data have different numbers of queries"); Debug.Assert(refreshData.QueryWorkItemsBefore.Count() == refreshData.Layouts.Count(), "Number of layouts does not match number of queries"); Debug.Assert(refreshData.QueryWorkItemsBefore.Count() == refreshData.QueryIsFlat.Count(), "Number of QueryIsFlat values does not match number of queries"); DateTime start = DateTime.Now; CustomXMLPart part = this.wordDocument.GetXmlPart(Constants.WorkItemNamespace); int n = refreshData.QueryWorkItemsBefore.Count(); QueryWorkItems[] queryWorkItemsBefore = refreshData.QueryWorkItemsBefore.ToArray(); QueryWorkItems[] queryWorkItemsAfter = refreshData.QueryWorkItemsAfter.ToArray(); bool[] queryIsFlat = refreshData.QueryIsFlat.ToArray(); LayoutInformation[] layouts = refreshData.Layouts.ToArray(); for (int queryIndex = 0; queryIndex < n; queryIndex++) { Func <int, string> queryBookmarkNamingFunction = (int id) => bookmarkNamingFunction(queryIndex, id); this.logger.Log(TraceEventType.Verbose, "Refreshing query {0}", queryIndex); // Compute the actual before work items that are still in the document. QueryWorkItems actualBeforeWorkItems = new QueryWorkItems(queryIndex, queryWorkItemsBefore[queryIndex].WorkItemIds.Where(id => this.FindBookmark(queryBookmarkNamingFunction(id)) != null).ToArray()); bool isManuallySorted = this.IsManuallySorted(queryWorkItemsBefore[queryIndex].WorkItemIds, queryBookmarkNamingFunction); if (!queryIsFlat[queryIndex] || (queryIsFlat[queryIndex] && !isManuallySorted)) { this.SortExistingWorkItems(actualBeforeWorkItems, queryWorkItemsAfter[queryIndex], queryBookmarkNamingFunction, cancellationToken); isManuallySorted = false; } IWorkItemLayout workItemLayout = new WorkItemLayout(layouts[queryIndex], this.teamProjectTemplate); this.AddNewWorkItems(actualBeforeWorkItems, queryWorkItemsAfter[queryIndex], workItemLayout, part, queryBookmarkNamingFunction, isManuallySorted, cancellationToken); } this.RefreshDeleteRemovedWorkItems(refreshData.QueryWorkItemsBefore.ToArray(), refreshData.QueryWorkItemsAfter.ToArray(), bookmarkNamingFunction, cancellationToken); this.RefreshRichTextContentControls(refreshData.WorkItemManager, cancellationToken); DateTime end = DateTime.Now; this.logger.Log(TraceEventType.Information, "Elapsed time to refresh was {0} seconds", (end - start).TotalSeconds); }
/// <summary> /// Maps work items into the document using the given layout. Each work item is bookmarked. /// </summary> /// <param name="workItems">The work items to be mapped into the document.</param> /// <param name="layout">The layout to be used to map the saved work items.</param> /// <param name="bookmarkNamingFunction">A function to return the bookmark to use for the given work item id.</param> /// <param name="cancellationToken">Used to cancel the save.</param> /// <remarks> /// It is assumed that the document already contains the XML data for the work items. /// </remarks> public void MapWorkItemsIntoDocument(WorkItemTree workItems, LayoutInformation layout, Func <int, string> bookmarkNamingFunction, CancellationToken cancellationToken) { if (workItems == null) { throw new ArgumentNullException("workItems"); } if (layout == null) { throw new ArgumentNullException("layout"); } if (bookmarkNamingFunction == null) { throw new ArgumentNullException("bookmarkNamingFunction"); } DateTime start = DateTime.Now; int count = 0; CustomXMLPart part = this.wordDocument.GetXmlPart(Constants.WorkItemNamespace); if (this.wordDocument.IsAtStart()) { this.wordDocument.InsertParagraph(ModelResources.FormatterStartOfImportBoilerPlate, Constants.NormalStyleName); } foreach (WorkItemTreeNode node in workItems.DepthFirstNodes()) { cancellationToken.ThrowIfCancellationRequested(); count++; IWorkItemLayout workItemLayout = new WorkItemLayout(layout, this.teamProjectTemplate); this.MapWorkItemIntoDocument(node, workItemLayout, bookmarkNamingFunction, part, InsertionPoint.CurrentLocation, 0); } if (this.wordDocument.IsAtEnd()) { this.wordDocument.InsertParagraph(ModelResources.FormatterEndOfImportBoilerPlate, Constants.NormalStyleName); } DateTime end = DateTime.Now; this.logger.Log(TraceEventType.Information, "Elapsed time to insert {0} items was {1} seconds", count, (end - start).TotalSeconds); }