我正在尝试设计一个控件,允许用户向上或向下滚动一系列数字(例如0-2000),同样可以向上或向下滚动列表。
我尝试在ListView
内使用GridView
或Flyout
,但加载数千件物品的速度太慢了。
现在我认为最好的方法可能是简单地模拟列表滚动而不实际拥有任何项目(即无限滚动选择器)。关于什么控件用作实现这样一个无限选择器的基础的任何建议?
答案 0 :(得分:3)
Here is looped virtualized scroller. It keeps only 5 items so you could add a lot of them. For selection, you may add an event on Item.
public sealed partial class MainPage
{
private static int Count = 20;
private static float ItemSize = 128;
private Visual _spawnerVisual;
private readonly List<ItemModel> _items = new List<ItemModel>();
private readonly List<Item> _selectedItems = new List<Item>();
private int _index;
private static readonly Random Random = new Random();
public MainPage()
{
InitializeComponent();
Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
PopulateItems();
SetInitialItems();
}
private void PopulateItems()
{
for (int i = 0; i < Count; i++)
{
_items.Add(new ItemModel());
}
}
private void SetInitialItems()
{
_index = -5;
for (int i = 0; i < 5; i++)
{
KillAtTop(true);
}
_spawnerVisual = ElementCompositionPreview.GetElementVisual(Spawner);
}
private void KillAtTop(bool atTop)
{
if (atTop)
{
if (_selectedItems.Count > 4)
{
_selectedItems.RemoveAt(0);
Spawner.Children.RemoveAt(0);
}
var index = GetIndex(_index + 3);
var item = new Item
{
Id = index,
BackColor = Color.FromArgb(255, (byte)Random.Next(0, 255), (byte)Random.Next(0, 255), (byte)Random.Next(0, 255)),
ItemSize = ItemSize,
ItemModel = _items[index],
OffsetY = (_index + 6) * ItemSize
};
_selectedItems.Add(item);
Spawner.Children.Add(item);
_index++;
}
else
{
if (_selectedItems.Count > 4)
{
_selectedItems.RemoveAt(_selectedItems.Count - 1);
Spawner.Children.RemoveAt(Spawner.Children.Count - 1);
}
var index = GetIndex(_index - 3);
var item = new Item
{
Id = index,
BackColor = Color.FromArgb(255, (byte)Random.Next(0, 255), (byte)Random.Next(0, 255), (byte)Random.Next(0, 255)),
ItemSize = ItemSize,
ItemModel = _items[index],
OffsetY = _index * ItemSize
};
_selectedItems.Insert(0, item);
Spawner.Children.Insert(0, item);
_index--;
}
}
private int GetIndex(int index)
{
index = index % _items.Count;
if (index > _items.Count - 1) return index - _items.Count;
if (index < 0) return _items.Count + index;
return index;
}
private void Slider_OnSetDelta(float deltaY)
{
SetPosition(deltaY);
}
public void SetPosition(float offsetY)
{
_spawnerVisual.Offset += new Vector3(0, offsetY / 10, 0);
if (_spawnerVisual.Offset.Y > -ItemSize * _index + ItemSize)
{
KillAtTop(false);
}
if (_spawnerVisual.Offset.Y < -ItemSize * _index)
{
KillAtTop(true);
}
}
}
Just add your ItemControl and call SetPosition to scroll. Should look like this:
答案 1 :(得分:1)
我尝试在Flyout中使用ListView或GridView,但是加载几千个项目只是太慢了。
根据您的要求,您不必一次创建所有项目。
您可以根据需要通过实施ISupportIncrementalLoading
界面加载其余项目。当用户即将结束用户界面上可用的项目时,它允许轻松创建一个集合,在该集合中以递增方式加载数据。使用它,我们可以获得快速&amp;加载大量记录时流体滚动。
public class ItemToShow : ObservableCollection<string>, ISupportIncrementalLoading
{
public int lastItem = 1;
public bool HasMoreItems
{
get
{
if (lastItem == 2000) return false;
else return true;
}
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
var progressBar = ((Window.Current.Content as Frame).Content as MainPage).MyProgressBar;
CoreDispatcher coreDispatcher = Window.Current.Dispatcher;
return Task.Run<LoadMoreItemsResult>(() =>
{
coreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
progressBar.IsIndeterminate = true;
progressBar.Visibility = Visibility.Visible;
});
List<string> items = new List<string>();
for (var i = 0; i < count; i++)
{
items.Add(string.Format("Items{0}", lastItem));
lastItem++;
if (lastItem == 2000)
break;
}
coreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
foreach (string item in items)
{
this.Add(item);
progressBar.Visibility = Visibility.Collapsed;
progressBar.IsHoldingEnabled = false;
}
});
return new LoadMoreItemsResult() { Count = count };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
<强>用法强>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView
x:Name="ListViewMain"
Margin="0,100,0,0"
Padding="100,0,0,10">
<ListView.Resources>
<DataTemplate x:Key="DataTemplateListViewMain">
<Grid
Width="100"
Height="100"
Background="LightGray">
<TextBlock
VerticalAlignment="Center"
FontSize="18"
Text="{Binding}"
TextAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.Resources>
<ListView.ItemTemplate>
<StaticResource ResourceKey="DataTemplateListViewMain" />
</ListView.ItemTemplate>
</ListView>
<ProgressBar
x:Name="MyProgressBar"
Height="10"
Margin="0,5,0,0"
VerticalAlignment="Top"
x:FieldModifier="public"
Visibility="Collapsed" />
</Grid>
<强> MainPage.xaml.cs中强>
private void Page_Loaded(object sender, RoutedEventArgs e)
{
ListViewMain.ItemsSource = new ItemToShow();
}