2012-09-24 73 views
1

我有一個不虛擬化的ListBox。我明顯錯過了一些東西,但找不到它。列表框不虛擬化

它實際上是一個ListBox內的列表框。外部ListBox有一個包含Expander的ItemTemplate。擴展器用於顯示一組項目。 Expander的內容是顯示項目的第二個ListBox。第二個ListBox上的ItemTemplate綁定到要顯示的實際Item。我的項目的ViewModel類具有許多屬性,這些屬性在調用Get屬性之前不會初始化數據。但是,WPF遍歷每個項目並導致初始化邏輯,我試圖避免。

我發現使用ListCollectionView.GroupDescription會導致ListBox不能虛擬化。現在我正在ViewModel中處理自己的分組。我的外部ListBox綁定到一個ObservableCollection(ItemGroupViewModel),其中ItemGroupViewModel有一個GroupName和一個Items列表。第二個ListBox綁定到ItemGroupViewModel中的Items。這並沒有解決問題。我也在調試時檢查了VirtualizingStackPanel.GetIsVirtualizing(),它返回true,但WPF仍然遍歷每一個項目。我已經進行了兩次檢查,以確保我的分組邏輯不會觸發每個項目中的數據初始化邏輯,這是我試圖避免的。

我認爲IsSharedSizeScope可能會導致ListBox渲染所有項目以確定列大小。所以我關閉了SharedSizeScope。仍然沒有虛擬化。

我錯過了什麼?

回答

2

它不是虛擬化的,因爲它在擴展器內部,擴展器的模板是headeredcontentcontrol(據我所知),它的模板包含一個stackpanel。

堆棧面板的內容永遠不會沿堆棧方向拉伸,因此您的列表框將始終具有它請求的所有空間,然後就不會獲得虛擬化。你的內部列表框也不會得到任何垂直滾動條。

你有一個解決方案(至少:)

1:maxheight設置你的內心列表框 - 可能是最容易。

希望它有幫助:)

+0

感謝符文。提供所有需要的空間的StackPanel是合理的。我會研究改變ControlTemplate。如果這不起作用,我會考慮使用TreeView。 – Jayson

+0

我看着擴展模板,並沒有StackPanel。只需一個用於標題的ToggleButton和用於內容的ContentPresenter。我搬到了樹上,發現了一些限制。沒有多重選擇和虛擬化似乎只對根項目起作用。啊。經過一些更多的研究後,我會在TreeView上發佈另一個問題。 – Jayson

+0

啊是的 - 我有點偏離它,它來自HeaderedContentControl,但有一個ControlTemplate實際上是一個dockpanel。所以解決方案2被排除了。當再次查看你的描述時,你將你的子列表框放在一個列表框中,該列表框中有一個用於其項目的堆棧面板。所以你的外部列表框虛擬化?我認爲你必須在你的內部列表框中設置MaxHeight來讓它們虛擬化。關於TreeView - 據我所知,treeview根本沒有虛擬化。 –