VirtualizingStackPanel、ItemsStackPanel和ItemsWrapGrid都是虚拟化布局控件,通常状况下在界面的布局上不多会用到这些虚拟化排列的控件,大部分都是封装在列表的布局面板上使用,主要的目的就是为了实现列表上大数据量的虚拟化,从而极大地提升列表的效率。那么其实这3个虚拟化布局控件都是列表控件的默认布局排列的方式,其中VirtualizingStackPanel控件是ListBox的默认布局面板,ItemsStackPanel是ListView的默认布局面板,ItemsWrapGrid是GridView的默认布局面板。html
VirtualizingStackPanel控件和ItemsStackPanel控件都是表示沿着水平方向或垂直垂直方向将内容虚拟化地排列在一行上。它们控件所实现的排列布局效果和StackPanel控件是同样的,不一样的是这些控件能够实现虚拟化的逻辑。对于数据较多的列表布局,使用VirtualizingStackPanel控件或者ItemsStackPanel控件会比StackPanel控件高效不少,由于虚拟化控件只是把当前屏幕范围内的数据显示出来,其余的数据都经过虚拟化的技术进行处理,并无进行UI的初始化显示,因此效率很高。ItemsWrapGrid控件实现的则是网格的虚拟化布局效果,虚拟化原理也是和ItemsStackPanel控件相似的,只不过他们排列的方式不同。编程
这些虚拟化排列布局控件会计算可见项的数量,并处理来自 ItemsControl(如 ListBox)的ItemContainerGenerator,以便只为可见项建立 UI 元素。仅当StackPanel中包含的项控件建立本身的项容器时,才会在该面板中发生虚拟化。 可使用数据绑定来确保发生这一过程,若是是直接建立列表的项元素而后添加为虚拟化排列布局控件的子对象,那么这种方式是不会进行虚拟化处理的。下面以ItemsStackPanel来讲明咱们如何去利用虚拟化排列布局控件去解决一些实际的问题。app
ItemsStackPanel是ListView元素的默认项宿主。使用ListView列表控件绑定数据的时候,默认是采用了ItemsStackPanel控件对数据项进行排列。若是你使用ItemsControl列表控件来展现数据,要给这个列表增长虚拟化的功能,ItemsStackPanel对象元素必须包含在一个ItemsPanelTemplate中。如今咱们再回过头来看本章的第一个例子,用ItemsControl控件绑定到2000个数据项的集合的时候,加载的速度很慢,这就是没有使用虚拟化的结果。若是在ItemsControl控件上使用ItemsStackPanel来进行虚拟化布局,那么你会发现加载的速度很是快。给ItemsControl控件添加ItemsStackPanel虚拟化布局,须要把代码修改为以下:布局
<ItemsControl x:Name="itemsControl"> <!--使用ItemsStackPanel控件做为ItemsControl的布局面板--> < ItemsControl.ItemsPanel> <ItemsPanelTemplate> <ItemsStackPanel/> </ItemsPanelTemplate> </ ItemsControl.ItemsPanel> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <ScrollViewer> <ItemsPresenter/> </ScrollViewer> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> ……省略若干代码 </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
若是在列表中须要使用到ItemsStackPanel控件虚拟化的技术的时候,还要注意一个事情是,不要破坏ScrollViewer和ItemsPresenter的结构,不然将实现不了虚拟化的效果。若是你在ScrollViewer和ItemsPresenter之间再添加一个StackPanel控件,以下所示:大数据
<ControlTemplate TargetType="ItemsControl"> <ScrollViewer> <StackPanel> <ItemsPresenter/> </StackPanel> </ScrollViewer> </ControlTemplate>
那么这时候,ItemsStackPanel控件会一次性把全部的数据都初始化,不会起到虚拟化的做用。由于ItemsStackPanel控件虚拟化的时候是根据每一个Item的固定的大小来进行布局的虚拟化处理的,当在ScrollViewer和ItemsPresenter中加入了其余的控件以后会破坏了ItemsStackPanel控件的虚拟化布局,致使ItemsStackPanel控件没法准确地测量出来列表的数据项的布局。this
一般咱们实现的列表布局大部分都是竖向的布局,包括GridView控件的布局总体上也是竖向的布局。那么ListView控件和ListBox控件默认都是竖向垂直滚动的列表,若是要让其水平滚动那么就须要自定义其布局的面板,这时候咱们就可使用ItemsStackPanel控件去实现了,若是咱们并不须要ListView控件的那么多的功能和效果,就能够直接使用最基本的列表控件ItemsControl控件搭配ItemsStackPanel控件去实现横向滚动的效果,而且带有虚拟化的功能。spa
下面咱们用一个例子使用ItemsControl控件横向滚动展现图片,在这个例子里面会使用到ItemsStackPanel控件的Horizontal布局。列表中会有100个数据项,咱们经过日志来查看其加载的数据项是怎样的。调试
代码清单11-7:横向虚拟化列表(源代码:第11章\Examples_11_7)日志
(1)首先,建立实体类和自定义的集合类,实体类Item和自定义的集合类ItemList。code
Item.cs文件主要代码 ------------------------------------------------------------------------------------------------------------------ public class Item { // 图片对象 public BitmapImage Image { get; set; } // 图片名字 public string ImageName { get; set; } }
ItemList.cs文件主要代码 ------------------------------------------------------------------------------------------------------------------ public class ItemList : IList { // 设置集合的数量为100 public ItemList() { Count = 100; } // 集合数量属性 public int Count { get; set; } // 根据索引返回数据项 public object this[int index] { get { // 加载的图片是程序里面的图片资源,5张图片循环加载 int imageIndex = 5 - index % 5; Debug.WriteLine("加载的集合索引是:" + index ); return new Item { ImageName = "图片" + index, Image = new BitmapImage(new Uri("ms-appx:///Images/" + imageIndex + ".jpg", UriKind.RelativeOrAbsolute)) }; } set { throw new NotImplementedException(); } } //……省略若干代码 }
(2)实现ItemsControl的横向虚拟化布局。
要实现ItemsControl的横向虚拟化布局,除了使用ItemsStackPanel控件的Horizontal布局,还须要在ItemsControl中设置ScrollViewer.HorizontalScrollBarVisibility="Auto",这样列表就能够水平滚动了。列表的代码以下:
MainPage.xaml文件主要代码 ------------------------------------------------------------------------------------------------------------------ <ItemsControl x:Name="list"> <!--使用ItemsStackPanel控件做为ItemsControl的布局面板--> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <ItemsStackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.Template> <ControlTemplate TargetType="ItemsControl"> <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility ="Disabled"> <ItemsPresenter/> </ScrollViewer> </ControlTemplate> </ItemsControl.Template> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel> <Image Source="{Binding Image}" Width="144" Height="240" Stretch="UniformToFill"></Image> <TextBlock Text="{Binding ImageName}"></TextBlock> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
MainPage.xaml.cs文件主要代码 ------------------------------------------------------------------------------------------------------------------ public MainPage() { InitializeComponent(); list.ItemsSource = new ItemList(); }
(3)列表的运行效果如图11.8所示,采用Debug调试下运行程序能够看到日志显示列表只是初始化了10个数据项,日志以下所示:
/*日志开始*/
加载的集合索引是:0
加载的集合索引是:1
加载的集合索引是:2
加载的集合索引是:3
加载的集合索引是:4
加载的集合索引是:5
加载的集合索引是:6
加载的集合索引是:7
加载的集合索引是:8
加载的集合索引是:9
/*日志开始*/
本文来源于《深刻理解Windows Phone 8.1 UI控件编程》
源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI
欢迎关注个人微博@WP林政
WP8.1技术交流群:372552293