예제 #1
0
        private void SelectAndSnapTo(LoopingSelectorItem item)
        {
            if (item == null)
            {
                return;
            }

            if (_selectedItem != null)
            {
                _selectedItem.SetState(IsExpanded ? LoopingSelectorItem.State.Expanded : LoopingSelectorItem.State.Normal, true);
            }

            if (_selectedItem != item)
            {
                _selectedItem = item;
                // Update DataSource.SelectedItem aynchronously so that animations have a chance to start.
                Dispatcher.BeginInvoke(() =>
                {
                    _isSelecting            = true;
                    DataSource.SelectedItem = item.DataContext;
                    _isSelecting            = false;
                });
            }

            _selectedItem.SetState(LoopingSelectorItem.State.Selected, true);

            TranslateTransform transform = item.Transform;

            if (transform != null)
            {
                if (Orientation == Orientation.Vertical)
                {
                    double newPosition = -transform.Y - Math.Round(item.ActualHeight / 2);
                    if (_panningTransform.Y != newPosition)
                    {
                        AnimatePanel(_selectDuration, _selectEase, newPosition);
                    }
                }
                else
                {
                    double newPosition = -transform.X - Math.Round(item.ActualWidth / 2);
                    if (_panningTransform.X != newPosition)
                    {
                        AnimatePanel(_selectDuration, _selectEase, newPosition);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Balances the items.
        /// </summary>
        private void Balance()
        {
            if (!IsReady)
            {
                return;
            }

            double actualItemWidth  = ActualItemWidth;
            double actualItemHeight = ActualItemHeight;

            if (Orientation == Orientation.Vertical)
            {
                _additionalItemsCount = (int)Math.Round((ActualHeight * 1.5) / actualItemHeight);
            }
            else
            {
                _additionalItemsCount = (int)Math.Round((ActualWidth * 1.5) / actualItemWidth);
            }

            LoopingSelectorItem closestToMiddle = null;
            int closestToMiddleIndex            = -1;

            if (_itemsPanel.Children.Count == 0)
            {
                // We need to get the selection and start from there
                closestToMiddleIndex = 0;
                _selectedItem        = closestToMiddle = CreateAndAddItem(_itemsPanel, DataSource.SelectedItem);

                if (Orientation == Orientation.Vertical)
                {
                    closestToMiddle.Transform.Y = -actualItemHeight / 2;
                    closestToMiddle.Transform.X = (ActualWidth - actualItemWidth) / 2;
                }
                else
                {
                    closestToMiddle.Transform.X = -actualItemWidth / 2;
                    closestToMiddle.Transform.Y = (ActualHeight - actualItemHeight) / 2;
                }

                closestToMiddle.SetState(LoopingSelectorItem.State.Selected, false);
            }
            else
            {
                closestToMiddleIndex = GetClosestItem();
                closestToMiddle      = (LoopingSelectorItem)_itemsPanel.Children[closestToMiddleIndex];
            }

            int itemsBeforeCount;
            LoopingSelectorItem firstItem = GetFirstItem(closestToMiddle, out itemsBeforeCount);

            int itemsAfterCount;
            LoopingSelectorItem lastItem = GetLastItem(closestToMiddle, out itemsAfterCount);

            // Does the top need items?
            if (itemsBeforeCount < itemsAfterCount || itemsBeforeCount < _additionalItemsCount)
            {
                while (itemsBeforeCount < _additionalItemsCount)
                {
                    object newData = DataSource.GetPrevious(firstItem.DataContext);
                    if (newData == null)
                    {
                        // There may be room to display more items, but there is no more data.
                        if (Orientation == Orientation.Vertical)
                        {
                            _maximumPanelScroll = -firstItem.Transform.Y - actualItemHeight / 2;
                        }
                        else
                        {
                            _maximumPanelScroll = -firstItem.Transform.X - actualItemWidth / 2;
                        }

                        if (_panelAnimation.To != null && (_isAnimating && _panelAnimation.To.Value > _maximumPanelScroll))
                        {
                            Brake(_maximumPanelScroll);
                        }
                        break;
                    }

                    LoopingSelectorItem newItem = null;

                    // Can an item from the bottom be re-used?
                    if (itemsAfterCount > _additionalItemsCount)
                    {
                        newItem  = lastItem;
                        lastItem = lastItem.Previous;
                        newItem.Remove();
                        newItem.Content = newItem.DataContext = newData;
                    }
                    else
                    {
                        // Make a new item
                        newItem = CreateAndAddItem(_itemsPanel, newData);

                        if (Orientation == Orientation.Vertical)
                        {
                            newItem.Transform.X = (ActualWidth - actualItemWidth) / 2;
                        }
                        else
                        {
                            newItem.Transform.Y = (ActualHeight - actualItemHeight) / 2;
                        }
                    }

                    // Put the new item on the top
                    if (Orientation == Orientation.Vertical)
                    {
                        newItem.Transform.Y = firstItem.Transform.Y - actualItemHeight;
                    }
                    else
                    {
                        newItem.Transform.X = firstItem.Transform.X - actualItemWidth;
                    }

                    newItem.InsertBefore(firstItem);
                    firstItem = newItem;

                    ++itemsBeforeCount;
                }
            }

            // Does the bottom need items?
            if (itemsAfterCount < itemsBeforeCount || itemsAfterCount < _additionalItemsCount)
            {
                while (itemsAfterCount < _additionalItemsCount)
                {
                    object newData = DataSource.GetNext(lastItem.DataContext);
                    if (newData == null)
                    {
                        // There may be room to display more items, but there is no more data.
                        if (Orientation == Orientation.Vertical)
                        {
                            _minimumPanelScroll = -lastItem.Transform.Y - actualItemHeight / 2;
                        }
                        else
                        {
                            _minimumPanelScroll = -lastItem.Transform.X - actualItemWidth / 2;
                        }

                        if (_panelAnimation.To != null && (_isAnimating && _panelAnimation.To.Value < _minimumPanelScroll))
                        {
                            Brake(_minimumPanelScroll);
                        }
                        break;
                    }

                    LoopingSelectorItem newItem = null;

                    // Can an item from the top be re-used?
                    if (itemsBeforeCount > _additionalItemsCount)
                    {
                        newItem   = firstItem;
                        firstItem = firstItem.Next;
                        newItem.Remove();
                        newItem.Content = newItem.DataContext = newData;
                    }
                    else
                    {
                        // Make a new item
                        newItem = CreateAndAddItem(_itemsPanel, newData);

                        if (Orientation == Orientation.Vertical)
                        {
                            newItem.Transform.X = (ActualWidth - actualItemWidth) / 2;
                        }
                        else
                        {
                            newItem.Transform.Y = (ActualHeight - ActualItemHeight) / 2;
                        }
                    }

                    // Put the new item on the bottom
                    if (Orientation == Orientation.Vertical)
                    {
                        newItem.Transform.Y = lastItem.Transform.Y + actualItemHeight;
                    }
                    else
                    {
                        newItem.Transform.X = lastItem.Transform.X + actualItemWidth;
                    }

                    newItem.InsertAfter(lastItem);
                    lastItem = newItem;

                    ++itemsAfterCount;
                }
            }

            _temporaryItemsPool = null;
        }