我正在尝试设计一个控件,允许用户向上或向下滚动一个范围内的数字(例如0-2000),具有类似于上下滚动列表的感觉。
为此,我尝试在Flyout中使用ListView或GridView,但仅加载几千个项目就太慢了。
现在我在想,最好的方法可能是简单地模拟列表滚动,而实际上没有任何项目(即无限滚动选择器)。关于使用什么控件作为实现这种无限选择器的基础,有什么建议吗?
发布于 2017-08-04 20:55:34
这是一个循环的虚拟化滚动条。它只保留了5个项目,所以你可以添加很多项目。对于选择,您可以在项目上添加事件。
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);
}
}
}只需添加您的ItemControl并调用SetPosition进行滚动。应该如下所示:

发布于 2017-08-04 12:05:02
我试着在弹出框中使用ListView或GridView,但是加载几千个项目太慢了。
根据您的要求,您不必一次创建所有项目。您可以根据需要通过implement ISupportIncrementalLoading接口加载剩余的项。它允许轻松地创建一个集合,当用户将要在用户界面上可用项的末尾时,数据被增量地加载到其中。使用它,我们可以在加载大量记录的同时获得快速流畅的滚动。
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();
}

https://stackoverflow.com/questions/45495328
复制相似问题