void RegisterForCallback() { if (!m_registeredForCallback) { global::System.Diagnostics.Debug.Assert(m_pendingElements.Count != 0); m_registeredForCallback = true; BuildTreeScheduler.RegisterWork( m_pendingElements[m_pendingElements.Count - 1].VirtInfo.Phase, // Use the phase of the last one in the sorted list DoPhasedWorkCallback); } }
void DoPhasedWorkCallback() { MarkCallbackRecieved(); if (m_pendingElements.Count > 0 && !BuildTreeScheduler.ShouldYield()) { var visibleWindow = m_owner.VisibleWindow; SortElements(visibleWindow); int currentIndex = m_pendingElements.Count - 1; do { var info = m_pendingElements[currentIndex]; var element = info.Element; var virtInfo = info.VirtInfo; var dataIndex = virtInfo.Index; int currentPhase = virtInfo.Phase; if (currentPhase > 0) { int nextPhase = VirtualizationInfo.PhaseReachedEnd; virtInfo.DataTemplateComponent.ProcessBindings(virtInfo.Data, -1 /* item index unused */, currentPhase, out nextPhase); ValidatePhaseOrdering(currentPhase, nextPhase); var previousAvailableSize = LayoutInformation.GetAvailableSize(element); element.Measure(previousAvailableSize); if (nextPhase > 0) { virtInfo.Phase = nextPhase; // If we are the first item or // If the current items phase is higher than the next items phase, then move to the next item. if (currentIndex == 0 || virtInfo.Phase > m_pendingElements[currentIndex - 1].VirtInfo.Phase) { currentIndex--; } } else { m_pendingElements.RemoveAt(currentIndex); currentIndex--; } } else { throw new InvalidOperationException("Cleared element found in pending list which is not expected"); } var pendingCount = (int)(m_pendingElements.Count); if (currentIndex == -1) { // Reached the top, start from the bottom again currentIndex = pendingCount - 1; } else if (currentIndex > -1 && currentIndex < pendingCount - 1) { // If the next element is oustide the visible window and there are elements in the visible window // go back to the visible window. bool nextItemIsVisible = SharedHelpers.DoRectsIntersect(visibleWindow, m_pendingElements[currentIndex].VirtInfo.ArrangeBounds); if (!nextItemIsVisible) { bool haveVisibleItems = SharedHelpers.DoRectsIntersect(visibleWindow, m_pendingElements[pendingCount - 1].VirtInfo.ArrangeBounds); if (haveVisibleItems) { currentIndex = pendingCount - 1; } } } } while (m_pendingElements.Count > 0 && !BuildTreeScheduler.ShouldYield()); } if (m_pendingElements.Count > 0) { RegisterForCallback(); } }