2013-01-24 256 views
9

我試圖改進WPF中我的樹形視圖的性能,當您打開一個包含6000個子項的節點時,目前需要大約13秒來顯示此項。我爲子集合使用了observablecollection,datatemplate綁定了約7列的TransactionViewModel類型,每個列都從視圖模型中提取一段數據。WPF渲染性能降低

6000個子項的transactionviewmodels被創建並實例化,但是因爲您尚未在視覺上顯示任何這些子視圖,所以首次展開節點時,需要13秒才能顯示。如果您隨後收縮並展開節點,則會立即顯示零時間以顯示/加載。唯一的區別是,第一次,TransactionviewModel的每個綁定依賴屬性都有它的getter被XAML綁定調用,當你第二次再次展開時,沒有任何事情發生變化,所以WPF並沒有再次調用getters並且可能只是在第二次展開時將內存中的綁定信息保存在內存中。

因此,該控件的可視化繪圖是即時的,但是第一次打開它(即使6000個transactionviewmodel對象已經完全加載到子集合中),純粹是對行進行渲染是需要花費時間的。

有趣的是,如果我將datatemplate更改爲不綁定到viewmodel對象上的ANY依賴項屬性,並輸出一個空格,它仍需要8秒才能加載。因此,即使沒有任何數據綁定調用,樹查看器也需要8秒來渲染6000行。超過5秒會給你每行5個綁定數據列,所以與基本渲染相比,這是一個很小的成本。

8s渲染6000空白行似乎對我來說很高。是否有什麼主要原因可能會發生,或者從數據模板將XAML渲染到樹視圖中時需要注意的一些事情?我試過只使用一個空的數據模板 - 即它裏面沒有空格,它仍然需要7秒。

鑑於它會立即崩潰並擴展,爲什麼當它甚至不渲染任何XAML或調用任何數據綁定時第一次花費這麼長時間?

此外,異步調用不是一個解決方案,因爲我的問題不是GUI響應,而是花費時間來加載數據。用戶需要比現在更快地獲得數據。

非常感謝

+0

您在使用虛擬化?當你開始渲染數以千計的UI對象時,WPF的確會變慢,所以通常你只想渲染可見的項目,而不是全部渲染,並且只需在滾動時替換控件背後的DataContext。我也仔細檢查確認它是導致延遲的UI渲染,而不是加載數據。 – Rachel

回答

10

它看起來像我需要在TreeView中啓用虛擬化。

Optimizing Performance: Controls

默認情況下,UI虛擬化的ListView和列表框控件 啓用時,他們的列表項綁定到數據。 TreeView的 虛擬化可以通過設置 VirtualizingStackPanel :: IsVirtualizing附加屬性爲true

+0

在我的情況下,它是VirtualizingPanel.IsVirtualizing VirtualizingStackPanel代替:: IsVirtualizing – Yogesh

+2

鏈接已經死了..更新https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/optimizing-performance-controls –

1

您的問題可能沒有渲染,但佈局 - 它有實例很多UI元素,以找到他們的大小,使其能正常大小一些UI元素(滑塊),以及這需要時間。渲染可能根本不會進入。

+0

這只是樹視圖控件的限制嗎?由於我所做的只是添加空白的子節點,並且仍然需要一段合理的時間。每行第二行開始包括小圖標圖像,它幾乎不可用。我可以使用哪些技巧來加快速度? – NZJames

3

如果一個TreeView包含很多項目,所花費的時間來加載可能會導致在用戶界面的顯著延遲量啓用。您可以通過將VirtualizingStackPanel.IsVirtualizing附加屬性設置爲true來改善加載時間。當用戶使用鼠標滾輪滾動TreeView或拖動滾動條的大拇指時,用戶界面的反應速度可能會很慢。通過將VirtualizingStackPanel.VirtualizationMode附加屬性設置爲回收,您可以在用戶滾動時提高TreeView的性能。

How to: Improve the Performance of a TreeView

XAML:

<TreeView Height="200" ItemsSource="{Binding Source={StaticResource dataItems}}" x:Name="myTreeView" 
     VirtualizingStackPanel.IsVirtualizing="True" 
     VirtualizingStackPanel.VirtualizationMode="Recycling"/> 

編程:

myTreeView.SetValue(VirtualizingStackPanel.IsVirtualizingProperty, true); 
myTreeView.SetValue(VirtualizingStackPanel.VirtualizationModeProperty, VirtualizationMode.Recycling)