3

スイッチとして機能する 3 つのアイテムからなる素敵なタイルのリストを作成しました。次のようになります。

タイルスイッチャー

いいですね。ええと、縦にスクロールするリストにこれらのタイルが約 130 個ありますが、ロードするのに時間がかかります。パフォーマンス分析ツールによると、各要素のレンダリングには約 18 ミリ秒かかり、レンダリング時間は約 2.3 秒です。デバイスでは、多くの場合その 2 倍です。これは実際には危機ではありませんが、これらの要素が描画されるまで、UI は完全に黒く反応しません。

オンラインでいくつかの調査を行った後、これは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>

ListBoxItemsSource はコード ビハインドで設定されています。

4

2 に答える 2

3

別のスレッドから非同期でリストボックスにデータを入力すると、UIが応答しなくなるのを防ぐことができます。

編集2:

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; }
}
于 2012-07-10T12:50:54.940 に答える
1

役立つかもしれないいくつかのアイデア:

  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-and-stackpanel-help-windows-phone-7-lists-scroll-smoothly-and-consistently.aspx
于 2012-07-10T16:14:37.337 に答える