ListBox优化初步(二)

上文解决了虚拟化的问题,使得类Grid的多列布局ListBox也能实现虚拟化,可以说性能已经有了飞跃

 

但我的书中圣在使用过程中,仍然发现滑动起来卡卡的,上文的Demo大家可能注意到,即使是WrapPanel也仅是加载的时候很慢,滑动的时候也是流畅的,本文的内容就是关于ListBoxItem的结构复杂度问题。

 

注意观察上文的Demo,大家可以发现,ListBox的ItemTemplete非常简单,一个简单的色块加一行文字,这种情况下,排除加载速度,那么滑动性能是我们能接受的,但是,书中圣是这样的情况:

002

1)使用图片

2)相对复杂的布局

结果就使得列表滑动起来跳帧非常严重

这里有几种解决方案,Alexis有一篇文章很好的总结了几种提高ListBox性能体验的方式:http://www.cnblogs.com/alexis/archive/2011/06/12/2040565.html

经过权衡,我决定采用LazyListBox,但是在使用过程中发现:

1)可能是因为图片的关系,导致简单模板和复杂模板在切换过程中非常生硬

2)只要出发滚动/滑动事件,那么就会重新渲染一次

所以最终令我哭笑不得的是,书中圣使用了该项技术后,体验反而不如原来的。这里要指出的是,如果你是纯文本的项,那么还是可以用LazyListBox的,我并不是否定他,而是说要因地制宜,根据自身的情况选用。

最终只能放弃使用,同时我注意到,当我不使用图片,或者将ListBox的ItemTemplete结构变得简单时,ListBox的性能大幅度提升,所以我决定精简模板结构。

这是原来的模板:

            <Grid CacheMode="BitmapCache" Height="200" Margin="{StaticResource PhoneMargin}" Width="190">
                <Border Margin="{StaticResource AppMainBookProjectionMargin}" Background="Transparent">
                    <toolkit:ContextMenuService.ContextMenu>
                        <toolkit:ContextMenu IsZoomEnabled="False" Opened="ContextMenu_Opened" Closed="ContextMenu_Closed">
                            <toolkit:MenuItem Header="{Binding Strings.ContextMenuDelete, Source={StaticResource ApplicationResources}}" Click="BookshelfBoxMenuItem_Click_Delete"/>
                        </toolkit:ContextMenu>
                    </toolkit:ContextMenuService.ContextMenu>
                    <toolkit:GestureService.GestureListener>
                        <toolkit:GestureListener Tap="Book_Tapped"/>
                    </toolkit:GestureService.GestureListener>
                    <Grid Margin="8,0,0,0">
	        			<Grid.RowDefinitions>
	        				<RowDefinition/>
	        				<RowDefinition Height="Auto"/>
	        			</Grid.RowDefinitions>
	        			<TextBlock Text="{Binding BookName}" 
	        				TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeMediumLarge}" d:LayoutOverrides="GridBox" Margin="{StaticResource AppMainBookInfoMargin}"/>
	        			<TextBlock Text="{Binding Author, Converter={StaticResource WriterFotmatConverter}}"
	        				Style="{StaticResource PhoneTextSubtleStyle}" Foreground="{StaticResource PhoneSubtleBrush}" Grid.Row="1" TextAlignment="Right" FontFamily="{StaticResource AppFont}" Margin="{StaticResource AppMainBookInfoHorizontalMargin}" TextWrapping="Wrap"/>
	        		</Grid>
				</Border>
                <Button x:Name="Bookmark" CacheMode="BitmapCache" Visibility="{Binding Bookmarks.Count, Converter={StaticResource BookmarkVisibilityConverter}}" Style="{StaticResource SimpleButton}" Click="BookmarkButton_Click_Show" FontFamily="{StaticResource AppFont}" Margin="{StaticResource AppMainBookmarkButtonMargin}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="{StaticResource AppBookmarkButtonBackground}" BorderBrush="{x:Null}" d:LayoutOverrides="HorizontalAlignment">
        			<Border Background="{StaticResource AppBookmarkButtonBackground}" Height="80" Width="55" />
        		</Button>
			</Grid>

 

可以看到其实也不是很复杂,无非就是几个Grid嵌套,这里是改进后的模板:

            <Border Background="Transparent">
                <Canvas CacheMode="BitmapCache" 
                        Margin="{StaticResource PhoneMargin}"
                        Height="200" Width="190">
                    <Rectangle x:Name="Background" CacheMode="BitmapCache" Fill="{StaticResource AppBookSingleBackground}" Height="200" Width="190" StrokeThickness="0"/>
                    <Button Visibility="{Binding Bookmarks.Count, Converter={StaticResource BookmarkVisibilityConverter}}" 
            		        x:Name="Bookmark" CacheMode="BitmapCache" 
                            Style="{StaticResource ButtonStyleForBookmark}" 
                            Background="{StaticResource AppBookmarkButtonBackground}"
            		        Canvas.Left="138" Canvas.Top="96" 
                            Width="50" Height="80"/>
                    <TextBlock Text="{Binding BookName}" 
            		           TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeMediumLarge}" 
            		           Canvas.Left="20" Canvas.Top="14" 
                               Width="108" Height="147"/>
                    <Border Height="170" Width="108"
            		        Canvas.Left="20" Canvas.Top="14">
                        <TextBlock Text="{Binding Author}" 
            			           FontSize="{StaticResource PhoneFontSizeNormal}" 
                                   Foreground="{StaticResource PhoneSubtleBrush}" 
            			           TextAlignment="Right" 
                                   TextWrapping="Wrap" 
            			           VerticalAlignment="Bottom"/>
                    </Border>
                    <Border Visibility="{Binding ManageState, Converter={StaticResource BookStateConverter}}"
                            Height="32" Width="32" Background="{StaticResource AppMainBooksStateDeleteBrush}" Canvas.Left="-10" Canvas.Top="-8"/>
                </Canvas>
            </Border>
 
 

变化在于:

1)取消Grid布局,改用Canvas,将嵌套结构尽量拉平,精简复杂度

2)取消对单个Item的手势和右键菜单监听,在ListBox外围放置统一的监听

经过这两个改造,列表在滑动时性能有少许上升,已经跳帧没有那么厉害了

 

一点小经验,欢迎大侠扔砖头

 

我的另一个产品博客,关于桌面小工具和Windows Phone 7应用作品的,欢迎访问:http://mohoo.cc

posted @ 2011-07-15 10:36  阿干@NET  阅读(2499)  评论(3编辑  收藏  举报