private bool CheckEnoughSpaceForItemInRow(WrapRow row, RadVirtualizingDataControlItem item, bool addingAtStart) { switch (this.orientationCache) { case Orientation.Horizontal: if (addingAtStart) { return(this.owner.availableWidth - (row.lastItem.horizontalOffsetCache + row.lastItem.width - row.firstItem.horizontalOffsetCache) >= item.width); } else { return(row.firstItem.horizontalOffsetCache >= item.width); } case Orientation.Vertical: if (addingAtStart) { return(this.owner.availableHeight - (row.lastItem.verticalOffsetCache + row.lastItem.height - row.firstItem.verticalOffsetCache) >= item.height); } else { return(row.firstItem.verticalOffsetCache >= item.height); } } return(false); }
private SingleItemAnimationContext GetAnimationContextForTarget(RadVirtualizingDataControlItem target, bool lookInAdded) { if (lookInAdded) { foreach (SingleItemAnimationContext c in this.scheduledAddAnimations) { if (c.AssociatedItem == target) { return(c); } } } else { foreach (SingleItemAnimationContext c in this.scheduledRemoveAnimations) { if (c.AssociatedItem == target) { return(c); } } } return(null); }
internal override void ReorderViewportItemsOnItemRemoved(int removedAt, RadVirtualizingDataControlItem removedContainer) { double correctionLength = this.GetItemLength(removedContainer); if (this.reorderMode == CollectionChangeItemReorderMode.MoveItemsDown) { ////Apply the aggregated height correction to all affected visual items reamining on the viewport for (int i = removedAt; i < this.owner.realizedItems.Count; i++) { RadVirtualizingDataControlItem itemToOffset = this.owner.realizedItems[i]; double currentVerticalOffset = itemToOffset.currentOffset; this.SetItemOffset(itemToOffset, currentVerticalOffset - correctionLength); } } else { ////Apply the aggregated height correction to all affected visual items reamining on the viewport for (int i = 0; i < removedAt; i++) { RadVirtualizingDataControlItem itemToOffset = this.owner.realizedItems[i]; double currentVerticalOffset = itemToOffset.currentOffset; this.SetItemOffset(itemToOffset, currentVerticalOffset + correctionLength); } } }
internal override void OnOrientationChanged(Orientation newValue) { base.OnOrientationChanged(newValue); if (this.owner == null || !this.owner.IsTemplateApplied) { return; } if (this.owner.GetItemCount() > 0) { this.owner.StopAllAddedAnimations(); this.owner.StopAllRemovedAnimations(); while (this.owner.realizedItems.Count > 0) { RadVirtualizingDataControlItem lastItem = this.owner.realizedItems[this.owner.realizedItems.Count - 1]; lastItem.SetVerticalOffset(0); lastItem.SetHorizontalOffset(0); this.owner.RecycleLastItem(); } this.wrapRows.Clear(); this.owner.BeginAsyncBalance(); this.owner.BalanceVisualSpace(); } }
internal override void ReorderViewportItemsOnItemReplaced(RadVirtualizingDataControlItem replacedItem) { if (this.reorderMode == CollectionChangeItemReorderMode.MoveItemsDown) { RadVirtualizingDataControlItem nextItem = replacedItem.next; while (nextItem != null) { this.SetItemOffset(nextItem, nextItem.previous.currentOffset + this.GetItemLength(nextItem.previous)); nextItem = nextItem.next; } } else { RadVirtualizingDataControlItem processedItem = replacedItem; while (processedItem != null) { if (processedItem.next != null) { this.SetItemOffset(processedItem, processedItem.next.currentOffset - this.GetItemLength(processedItem)); } processedItem = processedItem.previous; } } }
internal override RadVirtualizingDataControlItem GetContainerForItem(IDataSourceItem item, int insertAt) { RadVirtualizingDataControlItem container = base.GetContainerForItem(item, insertAt); this.allItemsExtent += this.GetItemExtent(container); return(container); }
internal override void OnAfterItemRemovedAnimationEnded(SingleItemAnimationContext context) { double startingOffset = context.AssociatedItem.currentOffset; double offset = context.RealizedLength; ////Apply the aggregated height correction to all affected visual items reamining on the viewport for (int i = 0; i < this.owner.realizedItems.Count; i++) { RadVirtualizingDataControlItem firstItem = this.owner.realizedItems[i]; if (firstItem.currentOffset > startingOffset) { if (firstItem.previous == null || (firstItem.previous != null && firstItem.previous.currentOffset + this.GetItemLength(firstItem.previous) <= firstItem.currentOffset - offset)) { this.SetItemOffset(firstItem, firstItem.currentOffset - offset); } else { break; } } } this.TranslateRemoveAnimatedItemsWithOffset(startingOffset, -offset); if (this.owner.IsLoaded) { this.ManageLowerViewport(false); this.CheckBottomScrollableBounds(); } }
/// <summary> /// Determines whether the specified data item is currently visible. /// </summary> /// <param name="dataItem"></param> /// <param name="includePartiallyVisibleItems"> /// If this parameter is set to <c>true</c>, then the partially visible items will also be included. /// </param> public bool IsItemInViewport(object dataItem, bool includePartiallyVisibleItems = true) { if (!this.IsOperational()) { return(false); } RadVirtualizingDataControlItem container = this.virtualizationStrategy.GetTopVisibleContainer(); int iterationStart = container.associatedDataItem.Index - this.firstItemCache.associatedDataItem.Index; double bottomViewportEdge = this.virtualizationStrategy.ViewportLength; for (int i = iterationStart; i < this.realizedItems.Count; i++) { container = this.realizedItems[i]; var itemTop = this.virtualizationStrategy.GetItemRelativeOffset(container); if (itemTop < bottomViewportEdge) { if (!includePartiallyVisibleItems && (itemTop < 0 || itemTop + virtualizationStrategy.GetItemLength(container) > bottomViewportEdge)) { continue; } if (dataItem.Equals(container.associatedDataItem.Value) && container.Visibility == Visibility.Visible) { return(true); } } else { break; } } return(false); }
private void SynchItemOffsetInRow(WrapRow row) { RadVirtualizingDataControlItem firstItem = row.firstItem; switch (this.orientationCache) { case Orientation.Horizontal: while (true) { firstItem.SetVerticalOffset(row.rowOffset); firstItem = firstItem.next; if (firstItem.wrapRow != row) { break; } } break; case Orientation.Vertical: while (true) { firstItem.SetHorizontalOffset(row.rowOffset); firstItem = firstItem.next; if (firstItem.wrapRow != row) { break; } } break; } }
internal virtual RadVirtualizingDataControlItem GetContainerForItem(IDataSourceItem item, int insertAt) { RadVirtualizingDataControlItem cp = null; if (this.owner.recycledItems.Count == 0) { cp = this.owner.GenerateContainerForItem(item); } else { cp = this.owner.recycledItems.Dequeue(); if ((this.owner.itemAddedAnimationCache != null && RadAnimationManager.IsAnimationScheduled(cp, this.owner.itemAddedAnimationCache)) || (this.owner.itemRemovedAnimationCache != null && RadAnimationManager.IsAnimationScheduled(cp, this.owner.itemRemovedAnimationCache))) { this.owner.recycledItems.Enqueue(cp); cp = this.owner.GenerateContainerForItem(item); } else { this.owner.OnContainerStateChanged(cp, item, ItemState.Realizing); this.owner.PrepareContainerForItemInternal(cp, item); cp.Visibility = Visibility.Visible; } } this.MeasureContainer(cp); this.InsertIntoViewport(cp, insertAt); this.owner.firstItemCache = this.owner.realizedItems[0]; this.owner.lastItemCache = this.owner.realizedItems[this.owner.realizedItems.Count - 1]; return(cp); }
internal override void ResetRealizationStartWhenLowerUIBufferRecycled(double position) { double bottomDifference = position - this.GetItemLength(this.owner.lastItemCache); if (bottomDifference > this.bottomVirtualizationThreshold) { int itemCount = (int)Math.Round(bottomDifference / this.averageItemLength, 0); RadVirtualizingDataControlItem firstRealizedDataItem = this.owner.FirstRealizedDataItem; int currentFirstItemIndex = 0; if (firstRealizedDataItem != null) { currentFirstItemIndex = Math.Max(firstRealizedDataItem.associatedDataItem.Index - itemCount, 0); } IDataSourceItem newDataItem = firstRealizedDataItem.associatedDataItem; while (newDataItem.Index > currentFirstItemIndex) { newDataItem = newDataItem.Previous; Debug.Assert(newDataItem != null, "The currentLastItemIndex should be within the bounds of the flattened view of the collection."); } this.owner.ClearContainerForItemInternal(this.owner.lastItemCache, this.owner.lastItemCache.associatedDataItem); RadVirtualizingDataControlItem newRealized = this.GetContainerForItem(newDataItem, false); double currentTop = this.ScrollOffset; this.SetItemOffset(newRealized, currentTop - this.GetElementCanvasOffset(this.owner.itemsPanel)); } }
internal override void ResetRealizationStartWhenUpperUIBufferRecycled(double position) { double topDifference = position + this.GetItemLength(this.owner.lastItemCache); if (topDifference < this.topVirtualizationThreshold) { int itemCount = (int)Math.Round(Math.Abs(topDifference) / this.averageItemLength, 0); RadVirtualizingDataControlItem lastRealizedDataItem = this.owner.LastRealizedDataItem; int currentLastItemIndex = this.owner.GetDataItemCount(); if (lastRealizedDataItem != null) { currentLastItemIndex = Math.Min(lastRealizedDataItem.associatedDataItem.Index + itemCount, currentLastItemIndex - 1); } IDataSourceItem newDataItem = lastRealizedDataItem.associatedDataItem; while (newDataItem.Index < currentLastItemIndex) { newDataItem = newDataItem.Next; Debug.Assert(newDataItem != null, "The currentLastItemIndex should be within the bounds of the flattened view of the collection."); } this.owner.ClearContainerForItemInternal(this.owner.lastItemCache, this.owner.lastItemCache.associatedDataItem); RadVirtualizingDataControlItem newRealized = this.GetContainerForItem(newDataItem, false); double currentBottom = this.ScrollOffset; this.SetItemOffset(newRealized, currentBottom - this.GetElementCanvasOffset(this.owner.itemsPanel)); } }
internal override void OnContainerSizeChanged(RadVirtualizingDataControlItem container, Size newSize, Size oldSize) { WrapRow parentRow = container.wrapRow.firstItem == container ? container.wrapRow.previous != null ? container.wrapRow.previous : container.wrapRow : container.wrapRow; this.allItemsExtent += this.orientationCache == Orientation.Horizontal ? newSize.Width - oldSize.Width : newSize.Height - oldSize.Height; parentRow.rowLength = 0; this.ReorderViewportItemsStartingAtRow(parentRow); }
internal override void ReorderViewportItemsOnItemReplaced(RadVirtualizingDataControlItem replacedItem) { WrapRow parentRow = replacedItem.wrapRow.firstItem == replacedItem ? replacedItem.wrapRow.previous != null ? replacedItem.wrapRow.previous : replacedItem.wrapRow : replacedItem.wrapRow; parentRow.rowLength = 0; this.ReorderViewportItemsStartingAtRow(parentRow); }
internal override RadVirtualizingDataControlItem GetContainerForItem(IDataSourceItem item, int insertAt) { RadVirtualizingDataControlItem container = base.GetContainerForItem(item, insertAt); this.realizedItemsLength += this.GetItemLength(container); return(container); }
internal RadVirtualizingDataControlItem GenerateContainerForItem(IDataSourceItem item) { RadVirtualizingDataControlItem cp = this.GetContainerForItemOverride(); this.OnContainerStateChanged(cp, item, ItemState.Realizing); this.itemsPanel.Children.Add(cp); this.PrepareContainerForItemOverride(cp, item); return(cp); }
internal virtual double GetItemLength(RadVirtualizingDataControlItem item) { if (this.LayoutOrientation == Orientation.Horizontal) { return(item.width); } return(item.height); }
internal virtual double GetItemRowOffset(RadVirtualizingDataControlItem item) { if (this.orientationCache == Orientation.Vertical) { return(item.verticalOffsetCache); } return(item.horizontalOffsetCache); }
internal void OnContainerSizeChanged(RadVirtualizingDataControlItem container, Size newSize, Size oldSize) { if (this.GetItemCount() == 0) { return; } this.virtualizationStrategy.OnContainerSizeChanged(container, newSize, oldSize); }
internal override bool PositionBottomRealizedItem(ref double visibleItemsBottom) { RadVirtualizingDataControlItem lastRealizedItem = this.owner.lastItemCache; double offset = lastRealizedItem.previous != null ? lastRealizedItem.previous.currentOffset + this.GetItemLength(lastRealizedItem.previous) : 0; this.SetItemOffset(lastRealizedItem, offset); visibleItemsBottom += this.GetItemLength(lastRealizedItem); return(true); }
internal override bool PositionTopRealizedItem(ref double visibleItemsTop) { RadVirtualizingDataControlItem firstRealizedItem = this.owner.firstItemCache; double verticalOffset = firstRealizedItem.next != null ? firstRealizedItem.next.currentOffset - this.GetItemLength(firstRealizedItem) : 0; this.SetItemOffset(firstRealizedItem, verticalOffset); visibleItemsTop -= this.GetItemLength(firstRealizedItem); return(true); }
internal virtual void PlaySingleItemRemovedAnimation(RadVirtualizingDataControlItem item) { int realizedIndex = item.associatedDataItem.Index - this.owner.firstItemCache.associatedDataItem.Index; RadAnimationManager.Play(item, this.owner.itemRemovedAnimationCache); this.owner.scheduledRemoveAnimations.Add(new SingleItemAnimationContext() { AssociatedItem = item, RealizedLength = this.GetItemLength(item), RealizedIndex = realizedIndex }); }
internal override void ReorderViewportItemsOnItemAddedOnTop(IDataSourceItem addedItem) { RadVirtualizingDataControlItem firstRealized = this.owner.firstItemCache; IDataSourceItem prev = this.owner.GetItemBefore(firstRealized.associatedDataItem); RadVirtualizingDataControlItem newFirst = this.GetContainerForItem(prev, false); newFirst.wrapRow = firstRealized.wrapRow; newFirst.wrapRow.firstItem = newFirst; this.ReorderViewportItemsStartingAtRow(newFirst.wrapRow); }
internal virtual void InvalidateItemOffset(RadVirtualizingDataControlItem item) { if (this.LayoutOrientation == Orientation.Vertical) { item.InvalidateVerticalOffset(); } else { item.InvalidateHorizontalOffset(); } }
private void TranslateRemoveAnimatedItemsWithOffset(double startingFrom, double offset) { foreach (SingleItemAnimationContext item in this.owner.scheduledRemoveAnimations) { RadVirtualizingDataControlItem associatedItem = item.AssociatedItem; if (associatedItem.currentOffset > startingFrom) { this.SetItemOffset(associatedItem, associatedItem.currentOffset + offset); } } }
internal virtual void SetItemOffset(RadVirtualizingDataControlItem item, double offset) { if (this.LayoutOrientation == Orientation.Vertical) { item.SetVerticalOffset(offset); } else { item.SetHorizontalOffset(offset); } }
/// <summary>Prepares the specified element to display the specified item. </summary> /// <param name="element">The element used to display the specified item.</param> /// <param name="item">The item to display.</param> protected virtual void PrepareContainerForItemOverride(RadVirtualizingDataControlItem element, IDataSourceItem item) { element.BindToDataItem(item); this.PrepareStyle(element, item); if (item.Value != RadListSource.UnsetObject) { this.PrepareDataItem(element, item); } }
internal virtual void ManageUpperViewport(bool recycle) { if (this.owner.firstItemCache == null) { return; } if (recycle) { double visibleItemsBottom = this.GetRealizedItemsBottom(); while (this.CanRecycleBottom(visibleItemsBottom)) { this.RecycleBottom(ref visibleItemsBottom); } if (this.owner.lastItemCache != null && this.owner.firstItemCache == this.owner.lastItemCache && !(this.owner.IsFirstItemFirstInListSource() || this.owner.IsLastItemLastInListSource())) { this.ResetRealizationStartWhenLowerUIBufferRecycled(visibleItemsBottom); } } bool processed = false; double visibleItemsTop = this.GetRealizedItemsTop(); while (this.CanRealizeTop(visibleItemsTop)) { IDataSourceItem item = this.owner.GetItemBefore(this.owner.firstItemCache.associatedDataItem); if (item == null) { break; } if (processed && this.owner.useAsyncBalance) { this.owner.ScheduleAsyncBalance(); return; } RadVirtualizingDataControlItem uiItem = this.GetContainerForItem(item, false); bool itemPositioned = this.PositionTopRealizedItem(ref visibleItemsTop); if (itemPositioned) { this.owner.OnContainerStateChanged(uiItem, item, ItemState.Realized); processed = true; } else { this.owner.RecycleFirstItem(); } } }
internal override double GetItemRelativeOffset(RadVirtualizingDataControlItem item) { switch (this.orientationCache) { case Orientation.Horizontal: return(item.verticalOffsetCache + Canvas.GetTop(this.owner.itemsPanel) - this.owner.manipulationContainer.VerticalOffset); case Orientation.Vertical: return(item.horizontalOffsetCache + Canvas.GetLeft(this.owner.itemsPanel) - this.owner.manipulationContainer.HorizontalOffset); } return(0); }
internal override RadVirtualizingDataControlItem GetTopVisibleContainer() { ////The approach here is to calculate the possible ////index of the topmost item by considering the upper buffer size ////and the average item height. In the ideal case of having equal height ////containers, the index will be calculated exactly. In case of wrong index calculation ////we estimate the direction we have to take in order to find the topmost item and ////interate to it. if (this.owner.realizedItems.Count == 0) { return(null); } if (this.averageItemLength == 0) { return(this.owner.firstItemCache); } double topThresholdAbs = Math.Abs(Math.Max(this.GetItemRelativeOffset(this.owner.firstItemCache), this.topVirtualizationThreshold)); int countOfTopItems = Math.Min((int)(topThresholdAbs / this.averageItemLength), this.owner.realizedItems.Count - 1); RadVirtualizingDataControlItem topElement = this.owner.realizedItems[countOfTopItems]; int deltaFactor = Math.Round(this.GetItemRelativeOffset(topElement), 1) > 0 ? -1 : 1; int realizedItemsCount = this.owner.realizedItems.Count; for (int i = countOfTopItems; i > -1 && i < realizedItemsCount; i += deltaFactor) { topElement = this.owner.realizedItems[i]; if (deltaFactor < 0) { if (Math.Round(this.GetItemRelativeOffset(topElement), 1) <= 0) { return(topElement); } } else { if (Math.Round(this.GetItemRelativeOffset(topElement), 1) == 0) { return(topElement); } if (Math.Round(this.GetItemRelativeOffset(topElement), 1) > 0) { return(topElement.previous != null ? topElement.previous : topElement); } } } return(topElement); }