Beispiel #1
0
            protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
            {
                var anchorIndex = context.RecommendedAnchorIndex;

                SuggestedAnchor = anchorIndex < 0 ? null : context.GetOrCreateElementAt(anchorIndex);
                return(base.MeasureOverride(context, availableSize));
            }
        // Figure out the extent of the layout by getting the number of items remaining
        // above and below the realized elements and getting an estimation based on
        // average item heights seen so far.
        private Rect EstimateExtent(VirtualizingLayoutContext context, Size availableSize)
        {
            double averageHeight = m_totalHeightForEstimation / m_numItemsUsedForEstimation;

            Rect extent = new Rect(0, 0, availableSize.Width, context.ItemCount * averageHeight);

            if (context.ItemCount > 0 && m_realizedElementBounds.Count > 0)
            {
                extent.Y = m_firstRealizedDataIndex == 0 ?
                           m_realizedElementBounds[0].Y :
                           m_realizedElementBounds[0].Y - (m_firstRealizedDataIndex - 1) * averageHeight;

                int lastRealizedIndex = m_firstRealizedDataIndex + m_realizedElementBounds.Count;
                if (lastRealizedIndex == context.ItemCount - 1)
                {
                    var lastBounds = m_realizedElementBounds[m_realizedElementBounds.Count - 1];
                    extent.Y = lastBounds.Bottom;
                }
                else
                {
                    var lastBounds                     = m_realizedElementBounds[m_realizedElementBounds.Count - 1];
                    int lastRealizedDataIndex          = m_firstRealizedDataIndex + m_realizedElementBounds.Count;
                    int numItemsAfterLastRealizedIndex = context.ItemCount - lastRealizedDataIndex;
                    extent.Height = lastBounds.Bottom + numItemsAfterLastRealizedIndex * averageHeight - extent.Y;
                }
            }

            DebugTrace("Extent " + extent + " with average height " + averageHeight);
            return(extent);
        }
Beispiel #3
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var realizationRect    = context.RealizationRect;
            int itemCount          = context.ItemCount;
            int firstRealizedIndex = FirstRealizedIndexInRect(realizationRect, itemCount);
            int lastRealizedIndex  = LastRealizedIndexInRect(realizationRect, itemCount);

            Debug.WriteLine("Measure:" + realizationRect.ToString());

            // Viewport + Buffer Rect.
            for (int currentIndex = firstRealizedIndex; currentIndex <= lastRealizedIndex; currentIndex++)
            {
                var element = context.GetOrCreateElementAt(currentIndex);
                element.Measure(new Size(ItemWidth, ItemHeight));
            }

            // Anchor
            var anchorIndex = context.RecommendedAnchorIndex;

            if (anchorIndex >= 0)
            {
                var anchorElement = context.GetOrCreateElementAt(anchorIndex);
                anchorElement.Measure(new Size(ItemWidth, ItemHeight));
            }

            return(new Size(ItemWidth, context.ItemCount * ItemHeight));
        }
        // The data collection has changed, since we are maintaining the bounds of elements
        // in the viewport, we will update the list to account for the collection change.
        protected override void OnItemsChangedCore(VirtualizingLayoutContext context, object source, NotifyCollectionChangedEventArgs args)
        {
            InvalidateMeasure();
            if (m_realizedElementBounds.Count > 0)
            {
                switch (args.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
                    break;

                case NotifyCollectionChangedAction.Replace:
                    OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
                    OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
                    break;

                case NotifyCollectionChangedAction.Remove:
                    OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
                    break;

                case NotifyCollectionChangedAction.Reset:
                    m_realizedElementBounds.Clear();
                    m_firstRealizedDataIndex = 0;
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
Beispiel #5
0
        protected override Rect GetExtent(
            Size availableSize,
            VirtualizingLayoutContext context,
            UIElement firstRealized,
            int firstRealizedItemIndex,
            Rect firstRealizedLayoutBounds,
            UIElement lastRealized,
            int lastRealizedItemIndex,
            Rect lastRealizedLayoutBounds)
        {
            var extent = base.GetExtent(
                availableSize,
                context,
                firstRealized,
                firstRealizedItemIndex,
                firstRealizedLayoutBounds,
                lastRealized,
                lastRealizedItemIndex,
                lastRealizedLayoutBounds);

            return(GetExtentFunc != null?GetExtentFunc(
                       availableSize,
                       context,
                       firstRealized,
                       firstRealizedItemIndex,
                       firstRealizedLayoutBounds,
                       lastRealized,
                       lastRealizedItemIndex,
                       lastRealizedLayoutBounds,
                       extent) : extent);
        }
Beispiel #6
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            var realizationRect    = context.RealizationRect;
            int itemCount          = context.ItemCount;
            int firstRealizedIndex = FirstRealizedIndexInRect(realizationRect, itemCount);
            int lastRealizedIndex  = LastRealizedIndexInRect(realizationRect, itemCount);

            Debug.WriteLine("Arrange:" + realizationRect.ToString());

            // Viewport + Buffer Rect.
            for (int currentIndex = firstRealizedIndex; currentIndex <= lastRealizedIndex; currentIndex++)
            {
                var element     = context.GetOrCreateElementAt(currentIndex);
                var arrangeRect = new Rect(0, currentIndex * ItemHeight, ItemWidth, ItemHeight);
                element.Arrange(arrangeRect);
                Debug.WriteLine("   Arrange:" + currentIndex + " :" + arrangeRect);
            }

            // Anchor
            var anchorIndex = context.RecommendedAnchorIndex;

            if (anchorIndex >= 0)
            {
                var anchor      = context.GetOrCreateElementAt(anchorIndex);
                var arrangeRect = new Rect(0, anchorIndex * ItemHeight, ItemWidth, ItemHeight);
                anchor.Arrange(arrangeRect);
                Debug.WriteLine("   Arrange:" + anchorIndex + " :" + arrangeRect);
            }

            return(finalSize);
        }
Beispiel #7
0
 protected override void UninitializeForContextCore(VirtualizingLayoutContext context)
 {
     base.UninitializeForContextCore(context);
     if (OnDetatchedFunc != null)
     {
         OnDetatchedFunc(context);
     }
 }
Beispiel #8
0
 protected override void InitializeForContextCore(VirtualizingLayoutContext context)
 {
     base.InitializeForContextCore(context);
     if (OnAttachedFunc != null)
     {
         OnAttachedFunc(context);
     }
 }
        // Figure out which index to use as the anchor and start laying out around.
        private int GetStartIndex(VirtualizingLayoutContext context, Size availableSize)
        {
            int  startDataIndex = -1;
            var  anchorIndex    = context.RecommendedAnchorIndex;
            bool isAnchorValid  = anchorIndex != -1;

            if (isAnchorValid)
            {
                if (IsRealized(anchorIndex))
                {
                    startDataIndex = anchorIndex;
                }
                else
                {
                    ClearRealizedRange();
                    startDataIndex = anchorIndex;
                }
            }
            else
            {
                // find first realized element that is visible in the viewport.
                startDataIndex = GetFirstRealizedDataIndexInViewport(context.RealizationRect);
                if (startDataIndex < 0)
                {
                    startDataIndex = EstimateIndexForViewport(context.RealizationRect, context.ItemCount);
                    ClearRealizedRange();
                }
            }

            // We have an anchorIndex, realize and measure it and
            // figure out its bounds.
            if (startDataIndex != -1 & context.ItemCount > 0)
            {
                if (m_realizedElementBounds.Count == 0)
                {
                    m_firstRealizedDataIndex = startDataIndex;
                }

                var newAnchor = EnsureRealized(startDataIndex);
                DebugTrace("Measuring start index " + startDataIndex);
                var desiredSize = MeasureElement(context, startDataIndex, availableSize);

                var bounds = new Rect(
                    0,
                    newAnchor ?
                    (m_totalHeightForEstimation / m_numItemsUsedForEstimation) * startDataIndex :
                    GetCachedBoundsForDataIndex(startDataIndex).Y,
                    availableSize.Width,
                    desiredSize.Height);
                SetCachedBoundsForDataIndex(startDataIndex, bounds);
            }

            return(startDataIndex);
        }
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            DebugTrace("ArrangeOverride: Viewport" + context.RealizationRect);
            for (int realizationIndex = 0; realizationIndex < m_realizedElementBounds.Count; realizationIndex++)
            {
                int currentDataIndex = m_firstRealizedDataIndex + realizationIndex;
                DebugTrace("Arranging " + currentDataIndex);

                // Arrange the child. If any alignment needs to be done, it
                // can be done here.
                var child         = context.GetOrCreateElementAt(currentDataIndex);
                var arrangeBounds = m_realizedElementBounds[realizationIndex];
                arrangeBounds.X -= m_lastExtent.X;
                arrangeBounds.Y -= m_lastExtent.Y;
                child.Arrange(arrangeBounds);
            }

            return(finalSize);
        }
        private Size MeasureElement(VirtualizingLayoutContext context, int index, Size availableSize)
        {
            var child = context.GetOrCreateElementAt(index);

            child.Measure(availableSize);

            int  estimationBufferIndex = index % m_estimationBuffer.Count;
            bool alreadyMeasured       = m_estimationBuffer[estimationBufferIndex] != 0;

            if (!alreadyMeasured)
            {
                m_numItemsUsedForEstimation++;
            }

            m_totalHeightForEstimation -= m_estimationBuffer[estimationBufferIndex];
            m_totalHeightForEstimation += child.DesiredSize.Height;
            m_estimationBuffer[estimationBufferIndex] = child.DesiredSize.Height;

            return(child.DesiredSize);
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var viewport = context.RealizationRect;

            DebugTrace("MeasureOverride: Viewport " + viewport);

            // Remove bounds for elements that are now outside the viewport.
            // Proactive recycling elements means we can reuse it during this measure pass again.
            RemoveCachedBoundsOutsideViewport(viewport);

            // Find the index of the element to start laying out from - the anchor
            int startIndex = GetStartIndex(context, availableSize);

            // Measure and layout elements starting from the start index, forward and backward.
            Generate(context, availableSize, startIndex, forward: true);
            Generate(context, availableSize, startIndex, forward: false);

            // Estimate the extent size. Note that this can have a non 0 origin.
            m_lastExtent         = EstimateExtent(context, availableSize);
            context.LayoutOrigin = new Point(m_lastExtent.X, m_lastExtent.Y);
            return(new Size(m_lastExtent.Width, m_lastExtent.Height));
        }
        private void Generate(VirtualizingLayoutContext context, Size availableSize, int anchorDataIndex, bool forward)
        {
            // Generate forward or backward from anchorIndex until we hit the end of the viewport
            int step = forward ? 1 : -1;
            int previousDataIndex = anchorDataIndex;
            int currentDataIndex  = previousDataIndex + step;
            var viewport          = context.RealizationRect;

            while (IsDataIndexValid(currentDataIndex, context.ItemCount) &&
                   ShouldContinueFillingUpSpace(previousDataIndex, forward, viewport))
            {
                EnsureRealized(currentDataIndex);
                DebugTrace("Measuring " + currentDataIndex);
                var  desiredSize    = MeasureElement(context, currentDataIndex, availableSize);
                var  previousBounds = GetCachedBoundsForDataIndex(previousDataIndex);
                Rect currentBounds  = new Rect(0,
                                               forward ? previousBounds.Y + previousBounds.Height : previousBounds.Y - desiredSize.Height,
                                               availableSize.Width,
                                               desiredSize.Height);
                SetCachedBoundsForDataIndex(currentDataIndex, currentBounds);
                previousDataIndex = currentDataIndex;
                currentDataIndex += step;
            }
        }
Beispiel #14
0
 protected override void OnElementMeasured(UIElement element, int index, Size availableSize, Size measureSize, Size desiredSize, Size provisionalArrangeSize, VirtualizingLayoutContext context)
 {
     base.OnElementMeasured(element, index, availableSize, measureSize, desiredSize, provisionalArrangeSize, context);
     if (OnElementMeasuredFunc != null)
     {
         OnElementMeasuredFunc(element, index, availableSize, measureSize, desiredSize, provisionalArrangeSize, context);
     }
 }
Beispiel #15
0
 protected override void OnLineArranged(int startIndex, int countInLine, double lineSize, VirtualizingLayoutContext context)
 {
     base.OnLineArranged(startIndex, countInLine, lineSize, context);
     if (OnLineArrangedFunc != null)
     {
         OnLineArrangedFunc(startIndex, countInLine, lineSize, context);
     }
 }
Beispiel #16
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var extent = base.MeasureOverride(context, availableSize);

            return(MeasureLayoutFunc != null?MeasureLayoutFunc(availableSize, context, extent) : extent);
        }
Beispiel #17
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            var extent = base.ArrangeOverride(context, finalSize);

            return(ArrangeLayoutFunc != null?ArrangeLayoutFunc(finalSize, context, extent) : extent);
        }
Beispiel #18
0
        protected override FlowLayoutAnchorInfo GetAnchorForRealizationRect(Size availableSize, VirtualizingLayoutContext context)
        {
            var anchorInfo = base.GetAnchorForRealizationRect(availableSize, context);

            return(GetAnchorForRealizationRectFunc != null?GetAnchorForRealizationRectFunc(availableSize, context, anchorInfo) : anchorInfo);
        }
Beispiel #19
0
        protected override FlowLayoutAnchorInfo GetAnchorForTargetElement(int targetIndex, Size availableSize, VirtualizingLayoutContext context)
        {
            var anchorInfo = base.GetAnchorForTargetElement(targetIndex, availableSize, context);

            return(GetAnchorForTargetElementFunc != null?GetAnchorForTargetElementFunc(targetIndex, availableSize, context, anchorInfo) : anchorInfo);
        }