internal void RemoveRange(int startIndex, int endIndex)
        {
            for (int i = startIndex; i <= endIndex; i++)
            {
                if (i > _items.Count)
                {
                    break;
                }

                StaggeredItem item = _items[i];
                item.Height = 0;
                item.Top    = 0;

                // We must recycle all elements to ensure that it gets the correct context
                RecycleElementAt(i);
            }

            foreach (var kvp in _columnLayout)
            {
                StaggeredColumnLayout layout = kvp.Value;
                for (int i = 0; i < layout.Count; i++)
                {
                    if ((startIndex <= layout[i].Index) && (layout[i].Index <= endIndex))
                    {
                        int numToRemove = layout.Count - i;
                        layout.RemoveRange(i, numToRemove);
                        break;
                    }
                }
            }
        }
        internal void AddItemToColumn(StaggeredItem item, int columnIndex)
        {
            if (_columnLayout.TryGetValue(columnIndex, out StaggeredColumnLayout columnLayout) == false)
            {
                columnLayout = new StaggeredColumnLayout();
                _columnLayout[columnIndex] = columnLayout;
            }

            if (columnLayout.Contains(item) == false)
            {
                columnLayout.Add(item);
            }
        }
        internal StaggeredItem GetItemAt(int index)
        {
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }

            if (index <= (_items.Count - 1))
            {
                return(_items[index]);
            }
            else
            {
                StaggeredItem item = new StaggeredItem(index);
                _items.Add(item);
                return(item);
            }
        }
Exemplo n.º 4
0
        /// <inheritdoc/>
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if ((context.RealizationRect.Width == 0) && (context.RealizationRect.Height == 0))
            {
                return(finalSize);
            }

            var state = (StaggeredLayoutState)context.LayoutState;

            // Cycle through each column and arrange the items that are within the realization bounds
            for (int columnIndex = 0; columnIndex < state.NumberOfColumns; columnIndex++)
            {
                StaggeredColumnLayout layout = state.GetColumnLayout(columnIndex);
                for (int i = 0; i < layout.Count; i++)
                {
                    StaggeredItem item = layout[i];

                    double bottom = item.Top + item.Height;
                    if (bottom < context.RealizationRect.Top)
                    {
                        // element is above the realization bounds
                        continue;
                    }

                    if (item.Top <= context.RealizationRect.Bottom)
                    {
                        double itemHorizontalOffset = (state.ColumnWidth * columnIndex) + (ColumnSpacing * columnIndex);

                        Rect      bounds  = new Rect(itemHorizontalOffset, item.Top, state.ColumnWidth, item.Height);
                        UIElement element = context.GetOrCreateElementAt(item.Index);
                        element.Arrange(bounds);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(finalSize);
        }
Exemplo n.º 5
0
        /// <inheritdoc/>
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            if (context.ItemCount == 0)
            {
                return(new Size(availableSize.Width, 0));
            }

            if ((context.RealizationRect.Width == 0) && (context.RealizationRect.Height == 0))
            {
                return(new Size(availableSize.Width, 0.0));
            }

            var state = (StaggeredLayoutState)context.LayoutState;

            double availableWidth  = availableSize.Width;
            double availableHeight = availableSize.Height;

            double columnWidth = Math.Min(DesiredColumnWidth, availableWidth);

            if (columnWidth != state.ColumnWidth)
            {
                // The items will need to be remeasured
                state.Clear();
            }

            state.ColumnWidth = Math.Min(DesiredColumnWidth, availableWidth);
            int numColumns = Math.Max(1, (int)Math.Floor(availableWidth / state.ColumnWidth));

            // adjust for column spacing on all columns expect the first
            double totalWidth = state.ColumnWidth + ((numColumns - 1) * (state.ColumnWidth + ColumnSpacing));

            if (totalWidth > availableWidth)
            {
                numColumns--;
            }
            else if (double.IsInfinity(availableWidth))
            {
                availableWidth = totalWidth;
            }

            if (numColumns != state.NumberOfColumns)
            {
                // The items will not need to be remeasured, but they will need to go into new columns
                state.ClearColumns();
            }

            if (RowSpacing != state.RowSpacing)
            {
                // If the RowSpacing changes the height of the rows will be different.
                // The columns stores the height so we'll want to clear them out to
                // get the proper height
                state.ClearColumns();
                state.RowSpacing = RowSpacing;
            }

            var columnHeights  = new double[numColumns];
            var itemsPerColumn = new int[numColumns];
            var deadColumns    = new HashSet <int>();

            for (int i = 0; i < context.ItemCount; i++)
            {
                var columnIndex = GetColumnIndex(columnHeights);

                bool          measured = false;
                StaggeredItem item     = state.GetItemAt(i);
                if (item.Height == 0)
                {
                    // Item has not been measured yet. Get the element and store the values
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(new Size(state.ColumnWidth, availableHeight));
                    item.Height = item.Element.DesiredSize.Height;
                    measured    = true;
                }

                double spacing = itemsPerColumn[columnIndex] > 0 ? RowSpacing : 0;
                item.Top = columnHeights[columnIndex] + spacing;
                double bottom = item.Top + item.Height;
                columnHeights[columnIndex] = bottom;
                itemsPerColumn[columnIndex]++;
                state.AddItemToColumn(item, columnIndex);

                if (bottom < context.RealizationRect.Top)
                {
                    // The bottom of the element is above the realization area
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }
                }
                else if (item.Top > context.RealizationRect.Bottom)
                {
                    // The top of the element is below the realization area
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }

                    deadColumns.Add(columnIndex);
                }
                else if (measured == false)
                {
                    // We ALWAYS want to measure an item that will be in the bounds
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(new Size(state.ColumnWidth, availableHeight));
                    if (item.Height != item.Element.DesiredSize.Height)
                    {
                        // this item changed size; we need to recalculate layout for everything after this
                        state.RemoveFromIndex(i + 1);
                        item.Height = item.Element.DesiredSize.Height;
                        columnHeights[columnIndex] = item.Top + item.Height;
                    }
                }

                if (deadColumns.Count == numColumns)
                {
                    break;
                }
            }

            double desiredHeight = state.GetHeight();

            return(new Size(availableWidth, desiredHeight));
        }