ListBox data virtualization is not taking effect

2019-01-19 07:16发布

问题:

I had 1000 items from xml and loaded them in a List object. List is databound to ListBox which is horizontally oriented so user can flip through items left to right or right to left. Since number of items are huge my app was quitting probably due to excessive memory usage. If I reduced the items to 50 it worked.

I found this article http://shawnoster.com/blog/post/Improving-ListBox-Performance-in-Silverlight-for-Windows-Phone-7-Data-Virtualization.aspx

and then this article on data virtualization

http://blogs.msdn.com/b/ptorr/archive/2010/08/16/virtualizing-data-in-windows-phone-7-silverlight-applications.aspx

After implementing a virtualized class implementing IList I see no difference. The this[] (below) is being called 1000 times still though I expected to it be called only 30-40 times since I understand UI is already virtualized in Listbox. Why is virtualization not kicking in?

object IList.this[int index]
{
    get
    {
        if (index >= cachedItems.Count)
        {
            //replenish cache code here
        }

        return cachedItems[index];
    }
    set
    {
        throw new NotImplementedException();
    }
}

Here is the XAML portion relevant to the problem. Hope this gives the full picture of the code. Not sure if Width=Auto has anything to do with it but I can't change it otherwise my swiping stops.

<ScrollViewer HorizontalScrollBarVisibility="Auto" Margin="0,0,0,0" Width="auto" x:Name="WordsScrollview" Opacity="1"  Grid.Row="1" RenderTransformOrigin="0.5,0.5">

    <ListBox x:Name="horizontalListBox" Width="auto" Height="Auto" >

        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal">
                </StackPanel>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>

        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Width="430" Text="{Binding Word}"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" TextAlignment="Center" />
                    <Image Height="290" HorizontalAlignment="Center" Name="image1" Stretch="Fill"  Width="430" Source="{Binding ImageFile}" Margin="10,50,10,0" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>

        <ListBox.Background>
            <SolidColorBrush />
        </ListBox.Background>

    </ListBox>

</ScrollViewer>

回答1:

Here is the XAML that is causing UI Virtualization to finally kick in.

        <ListBox x:Name="horizontalListBox"   Height="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" >

                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel Orientation="Horizontal">

                        </VirtualizingStackPanel>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>

                            <StackPanel>
                                <TextBlock Width="430" Text="{Binding Word}"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" TextAlignment="Center" />

                                <Image Height="290" HorizontalAlignment="Center" Name="image1" Stretch="Fill"  Width="430" Source="{Binding ImageFile}" Margin="10,50,10,0" />
                               </StackPanel>

                    </DataTemplate>
                </ListBox.ItemTemplate>
                <ListBox.Background>
                    <SolidColorBrush />
                </ListBox.Background>
            </ListBox>


回答2:

at the following article it is explained that wrapping a virtualizing UI control in a ScrollViewer will give it infinite space, effectively disabling UI virtualization

http://blogs.msdn.com/b/mcsuksoldev/archive/2010/04/13/performance-characteristics-of-the-silverlight-datagrid.aspx