2016-02-22 36 views
0

我寫一個Windows應用程序8.1,我現在用了很長的GridView。我正在使用UI虛擬化,而視圖模型包含一個包含100K項目的可觀察集合。ItemsWrapGrid隱藏物品通過偏移

<GridView ItemsSource="{Binding Items}"> 
    <GridView.ItemsPanel> 
     <ItemsPanelTemplate> 
      <ItemsWrapGrid Orientation="Vertical"/> 
     </ItemsPanelTemplate> 
    </GridView.ItemsPanel> 
    <GridView.ItemTemplate> 
     <DataTemplate> 
      <Border 
       Background="LightBlue" 
       Height="200" Width="200" 
       > 
       <TextBlock 
        Text="{Binding Index}" 
        VerticalAlignment="Center" HorizontalAlignment="Center" 
        FontSize="30" 
        /> 
      </Border> 
     </DataTemplate> 
    </GridView.ItemTemplate> 
</GridView> 

在屏幕上,它看起來像這樣: enter image description here

當使用默認項面板(ItemsWrapGrid)和朝列表的末尾滾動,在某一時刻開始的項目消失。

enter image description here

我與物品的各種大小進行了測試,並削波總是開始於同一滾動偏移量(約200萬個像素)。當我用WrapGrid替換面板時,錯誤不會發生。據我所知,ItemsWrapGrid具有更好的虛擬化,並想使用它,但這個錯誤當然是不能接受的。

有沒有解決這個錯誤的方式,同時仍使用ItemsWrapGrid

+0

我可以看看,你可以分享你的代碼? – ezaspi

+0

該問題包含您需要的所有代碼。只需將數據上下文設置爲包含名爲Items的屬性的任何類,其中包含1000000個對象,您將看到它。 –

+0

視圖嘗試呈現時,內存不足。也就是說,在我的Observable集合被填充並且xaml視圖開始顯示之後,我得到System.OutOfMemoryException。你是否正在做任何事情來避免OutOfMemoryException? – ezaspi

回答

1

只是發表我的OutOfMemoryException異常的窘境後,我做了一點點研究,我認爲我有你的解決方案,我發現這一點:

視口的概念是UI虛擬化至關重要的,因爲框架必須創建可能顯示的元素。通常, 控件的視口是邏輯控件的範圍。例如,一個ListView的視口是ListView元素的寬度和 的高度。一些面板允許子元素 不受限制的空間,例如ScrollViewer和網格,其中 自動調整大小的行或列。當一個虛擬化的ItemsControl放置 在那樣的面板,它需要足夠的空間來顯示所有其 項,這違背了虛擬化的。通過在ItemsControl上設置 寬度和高度來恢復虛擬化。 ListView and GridView UI optimization

所以我這個添加到你的GridView的ItemsSource:

<GridView ItemsSource="{Binding Items}" VirtualizingStackPanel.VirtualizationMode="Recycling" Width="800" Height="800"> 

它看起來像它需要一個寬度和高度。 enter image description here

+0

謝謝,但GridView坐落在一個有寬度和高度的容器內(它不是一個滾動查看器或任何賦予它無限空間的任何東西)。實際上,虛擬化的作品!我正在使用一種特殊類型的可觀察集合,它會懶散地創建它的項目,所以我確信虛擬化本身能夠工作(它也回答了您的第一個關於如何避免內存問題的問題)。唯一的問題是它沒有呈現通過2000000像素寬度的項目。 –

+0

如何檢查「2000000像素寬度」?但是這似乎違背了將像素限制在視口內的視口思想? – ezaspi

+0

無論如何,我認爲這很有趣,因爲我不需要寫點東西來使用虛擬化。我認爲微軟解釋的概念和延遲加載集合是兩回事。微軟定義的虛擬化似乎旨在避免嘗試顯示「200萬像素」。 – ezaspi