首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用UWP模拟无限滚动选择器的最简单方法

问用UWP模拟无限滚动选择器的最简单方法
EN

Stack Overflow用户
提问于 2017-08-04 06:09:56
回答 2查看 838关注 0票数 0

我正在尝试设计一个控件,允许用户向上或向下滚动一个范围内的数字(例如0-2000),具有类似于上下滚动列表的感觉。

为此,我尝试在Flyout中使用ListView或GridView,但仅加载几千个项目就太慢了。

现在我在想,最好的方法可能是简单地模拟列表滚动,而实际上没有任何项目(即无限滚动选择器)。关于使用什么控件作为实现这种无限选择器的基础,有什么建议吗?

EN

回答 2

Stack Overflow用户

发布于 2017-08-04 20:55:34

这是一个循环的虚拟化滚动条。它只保留了5个项目,所以你可以添加很多项目。对于选择,您可以在项目上添加事件。

代码语言:javascript
复制
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进行滚动。应该如下所示:

​

​

票数 3
EN

Stack Overflow用户

发布于 2017-08-04 12:05:02

我试着在弹出框中使用ListView或GridView,但是加载几千个项目太慢了。

根据您的要求,您不必一次创建所有项目。您可以根据需要通过implement ISupportIncrementalLoading接口加载剩余的项。它允许轻松地创建一个集合,当用户将要在用户界面上可用项的末尾时,数据被增量地加载到其中。使用它,我们可以在加载大量记录的同时获得快速流畅的滚动。

代码语言:javascript
复制
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>();
    }
}

使用

代码语言:javascript
复制
<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

代码语言:javascript
复制
private void Page_Loaded(object sender, RoutedEventArgs e)
 {
     ListViewMain.ItemsSource = new ItemToShow();
 }

​

​

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45495328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档