ListBox优化初步(二)
上文解决了虚拟化的问题,使得类Grid的多列布局ListBox也能实现虚拟化,可以说性能已经有了飞跃
但我的书中圣在使用过程中,仍然发现滑动起来卡卡的,上文的Demo大家可能注意到,即使是WrapPanel也仅是加载的时候很慢,滑动的时候也是流畅的,本文的内容就是关于ListBoxItem的结构复杂度问题。
注意观察上文的Demo,大家可以发现,ListBox的ItemTemplete非常简单,一个简单的色块加一行文字,这种情况下,排除加载速度,那么滑动性能是我们能接受的,但是,书中圣是这样的情况:
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