/// <summary>
/// Balances the items.
/// </summary>
private void Balance()
{
if (!IsReady)
{
return;
}
double actualItemWidth = ActualItemWidth;
double actualItemHeight = ActualItemHeight;
_additionalItemsCount = (int)Math.Round((ActualHeight * 1.5) / actualItemHeight);
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);
closestToMiddle.Transform.Y = -actualItemHeight / 2;
closestToMiddle.Transform.X = (ActualWidth - actualItemWidth) / 2;
closestToMiddle.SetState(LoopingSelectorItem.State.Selected, false);
}
else
{
closestToMiddleIndex = GetClosestItem();
closestToMiddle = (LoopingSelectorItem)_itemsPanel.Children[closestToMiddleIndex];
}
if (IsExpanded)
{
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.
_maximumPanelScroll = -firstItem.Transform.Y - actualItemHeight / 2;
if (_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);
newItem.Transform.X = (ActualWidth - actualItemWidth) / 2;
}
// Put the new item on the top
newItem.Transform.Y = firstItem.Transform.Y - actualItemHeight;
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.
_minimumPanelScroll = -lastItem.Transform.Y - actualItemHeight / 2;
if (_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);
newItem.Transform.X = (ActualWidth - actualItemWidth) / 2;
}
// Put the new item on the bottom
newItem.Transform.Y = lastItem.Transform.Y + actualItemHeight;
newItem.InsertAfter(lastItem);
lastItem = newItem;
++itemsAfterCount;
}
}
_temporaryItemsPool = null;
}
}