如何创建一个快速装载包装列表框?(How to create a fast loading wrap

2019-09-19 07:26发布

我做了作为开关工作砖一个可爱的小三项目范围内的清单。 它看起来是这样的:

看起来不错吧? 嗯,我有这些砖约130在垂直滚动列表,它需要年龄的负荷。 根据性能分析工具,每个单元大约需要18ms内渲染 - 这给了我大约2.3第二渲染时间。 在设备上,它往往是两倍的时间。 该不会真的是一个危机,但用户界面完全是黑色的,反应迟钝,直到这些元素已经制定。

一些研究联机后,我意识到这是因为WrapPanel从工具箱控件不其虚拟化项目-从而使GPU渲染的所有对象一次(在这个过程中使用了大量的内存)。

现在,有没有办法让这个走得更快?

XAML:

<ListBox x:Name="ChannelsListBox" Grid.Row="2" Margin="0,40,0,0">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <toolkit:WrapPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.Template>
        <ControlTemplate>
            <ItemsPresenter />
        </ControlTemplate>
    </ListBox.Template>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="ChannelTile" Margin="6,6,6,6" Tap="ChannelTile_Tap">
                <!-- context menu code removed -->
                <Rectangle Width="136" Height="136" Fill="{StaticResource LightGrayColor}" />    
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

ListBox的ItemsSource时被设置在代码隐藏-如果你想知道。

Answer 1:

好吧,如果你从另一个线程异步填充列表框,就能避免反应迟钝UI。

EDITED2:

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        /* In the xaml code:
           <ListBox x:Name="ChannelsListBox" ItemsSource="{Binding ListOfTestClasses}" ...
        */

        var vm = new MainPageViewModel();
        DataContext = vm;

        vm.StartLoadingDataAsync(10000);
    }
}

public class MainPageViewModel
{
    public ObservableCollection<TestClass> ListOfTestClasses { get; set; }
    private BackgroundWorker workerThread;
    public MainPageViewModel()
    {
        ListOfTestClasses = new ObservableCollection<TestClass>();
        workerThread = new BackgroundWorker();
        workerThread.DoWork += new DoWorkEventHandler((object sender, DoWorkEventArgs e) =>
        {
            for (int i = 0; i < (int)e.Argument; i++)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    ListOfTestClasses.Add(new TestClass { Text = "Element " + (i + 1) });
                });

                Thread.Sleep(150);
            }
        });
    }

    public void StartLoadingDataAsync(int numberOfElements)
    {
        workerThread.RunWorkerAsync(numberOfElements);   
    }
}

public class TestClass
{
    public string Text { get; set; }
}


Answer 2:

一些想法可能会有所帮助:

  1. 查找或实施虚拟化WrapPanel。 这是最合适的解决方案,但我不认为我已经看到了一个坚实的实现一个呢。 但是,为了这个目的,也许你并不需要完美,可以蒙混过关的东西别人已经写了。
  2. 使用父虚拟化包含水平StackPanel的儿童垂直的StackPanel。 要做到这一点,你需要重新塑造你的数据的单一序列分为3项条目的短序列。 然而,这可能不是太硬,应该给你最理想的解决方案的优势。
  3. 考虑像我一样的DeferredLoadListBox实施“懒”的容器。 其基本思路是,直到他们出现在屏幕上呈现延迟容器。 我在这里有更多的信息和示例代码: http://blogs.msdn.com/b/delay/archive/2010/09/08/never-do-today-what-you-can-put-off-till-tomorrow -deferredloadlistbox-和StackPanel中的帮助窗口电话-7-列表,滚动顺畅和-consistently.aspx


文章来源: How to create a fast loading wrapping ListBox?