今天和大家分享一些關於windows phone ui虛擬化和數據虛擬化的一些知識。
也順便回答我上一篇【LongListSelector 控件 在 wp7 和wp8中的不同之處】里,留下的那個問題,微軟為什么推薦使用longlistselector.
如果不是新人,那么對於"虛擬化"這個詞應該不陌生。
"虛擬化"簡單來說,就是在數據量很大的時候,我們只加載與可視區域(如手機屏幕)相應的少量數據。
我們先來看一下UI虛擬化。
一:Windows phone UI虛擬化
對於wp的ui虛擬化,其實我們並不需要花太多心思,因為系統自帶且用的最多的listbox 和longlistselector。
已經是幫我們實現了虛擬化。我們只需要注意別把美好的虛擬化破壞掉就好了。
1.首先,演示一下虛擬化。

MainPageViewMode.cs
public class MainPageViewModel
{
//省略
public MainPageViewModel()
{ //我們模擬1000條商品數據
listProduct = new List<Product>(1000);
for (int i = 0; i < 1000; i++)
{
listProduct.Add(new Product { Id = i, Name = "產品-" + rnd.Next(1000, 10000).ToString(), Category = "" });
} } }
Mainpage.xaml
<DataTemplate x:Key="LBDataTemplate">
<Grid Loaded="Grid_Loaded" d:DesignWidth="411.045" d:DesignHeight="78.209">
<TextBlock HorizontalAlignment="Left" Margin="10,17,0,25" TextWrapping="Wrap" Foreground="Black"
Text="{Binding Name}" Height="36" Width="197" FontSize="30"/>
</Grid>
</DataTemplate>
<ListBox Background="AliceBlue" ItemsSource="{Binding ListProduct}" x:Name="listbox" Grid.Row="1" ItemTemplate="{StaticResource LBDataTemplate}" />
Loaded="Grid_Loaded" 此事件觸發說明模板被加載。這里我們用的是ListBox控件
MainPage.cs
MainPageViewModel vm;
public MainPage()
{
InitializeComponent();
vm= new MainPageViewModel();
LayoutRoot.DataContext = vm;
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
vm.LoadItemCounter++;//界面上item被渲染的數目
}


我們看到我們綁定的數據源有1000條數據,頁面加載后item只渲染了21個。看似是有這樣一個規律的 可視區域數目*2+3
隨着我們滑動列表,Item也在不斷被渲染。

嗯哪,這就是所謂的UI虛擬化了。
2.常見的破壞虛擬化的場景
很多時候,我們在編輯模板的時候,會破壞掉虛擬化。看下面

當我們編輯ListBox的ItemsPanel的時候,工具幫我們自動生成了下面的代碼。
<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
<StackPanel/>
</ItemsPanelTemplate>
這時候我們再次運行

WoW ! 這次頁面一加載,ListBox就在不停地渲染Item.直至全部!
為什么會產生這種情況?
因為實現listbox的關鍵是默認的容器 VirtualizingStackPanel 通過工具編輯變成了StackPanel
改回VirtualizingStackPanel
<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
<VirtualizingStackPanel/>
</ItemsPanelTemplate>

呼! 星星又亮了!
好,到這里們我己經掌握了,什么是UI虛擬化,如何避免常見的破壞UI虛擬化的場景。
以及如何判斷我們對控件更改后,節操和虛擬化還在不在。
媽媽再也不用擔心我們不小心破壞虛擬化了!
下面我們來看一下LonglistSelector
還是上面的例子。我們把<ListBox 換成 <phone:LongListSelector 去掉ItemsPanel="{StaticResource ItemsPanelTemplate}"

還是虛擬化,只不過默認生成的item數不一樣了。
那么為什么微軟官方推薦我們用longlistselector代替ListBox呢?
我們繼續滑動。
看輸出!

