Beispiel #1
0
 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);
     }
 }
Beispiel #2
0
        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();
            }
        }