2010-12-28 16 views
13

Próbuję zrozumieć tę funkcję wirtualizacji, nie jestem pewien, czy rozumiem ją źle lub co się dzieje, ale używam profilera pamięci ANTS, aby sprawdzić liczbę elementów w zwirtualizowany TreeView, który stale rośnie. Mam TreeView z 1 001 przedmiotami (1 root, 1000 podelementów) i zawsze dostaję do 1 001 TreeViewItems, 1 001 ToggleButtons i 1 001 TextBlocks. Czy wirtualizacja nie ma na celu ponownego użycia przedmiotów? Jeśli tak, dlaczego miałbym mieć 1 001 każdego? Ponadto obiekt CleanUpVirtualizedItem nigdy nie jest uruchamiany.Wirtualizacja drzewa WPF TreeView

Daj mi znać, jeśli rozumiem to źle i jeśli masz zasoby, jak z tego korzystać. Szukałem w Internecie, ale nie znalazłem nic przydatnego.

EDIT:

Nawet pamięć używana przez drzewo wyrasta z aporx. 4mb do 12mb, gdy rozwijam i przewijam wszystkie przedmioty.

Daj mi znać dzięki.

To jest mój kod.

XAML:

<Window x:Class="RadTreeViewExpandedProblem.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <TreeView x:Name="treeView" 
        VirtualizingStackPanel.IsVirtualizing="True" 
        VirtualizingStackPanel.CleanUpVirtualizedItem="TreeView_CleanUpVirtualizedItem"> 
      <TreeView.ItemsPanel> 
       <ItemsPanelTemplate> 
        <VirtualizingStackPanel /> 
       </ItemsPanelTemplate> 
      </TreeView.ItemsPanel> 
     </TreeView> 
    </Grid> 
</Window> 

C#:

public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      TreeViewItem rootItem = new TreeViewItem() { Header = "Item Level 0" }; 

      for (int i = 0; i < 1000; i++) 
      { 
       TreeViewItem itemLevel1 = new TreeViewItem() { Header = "Item Level 1" }; 

       itemLevel1.Items.Add(new TreeViewItem()); 

       rootItem.Items.Add(itemLevel1); 
      } 

      treeView.Items.Add(rootItem); 
     } 

     private void TreeView_CleanUpVirtualizedItem(object sender, CleanUpVirtualizedItemEventArgs e) 
     { 

     } 
    } 

Odpowiedz

4

Ok, problem polega na tym, że wirtualizacja działa tylko wtedy, gdy TreeView używa wiązania, a nie, gdy węzły są generowane jeden po drugim w kodzie takim jak mój przykład. Co za porażka.

+2

To nie powinno być zbyt wielkim problemem, wystarczy użyć ObservableCollection, aby powiązać widok drzewa i dodać swoje przedmioty do kolekcji, gdy jest to potrzebne - jest to bardziej idiomatyczne Oczywiście WPF, nie chcesz ręcznie dodawać elementów bezpośrednio. – BrokenGlass

+0

Podoba mi się twój pomysł. Sposób, w jaki będę wiedzieć, kiedy potrzebuję więcej przedmiotów, to przewijanie w górę lub w dół po drzewie. Czy myślisz, że to zadziała z takim podejściem? – Carlo

+0

@Calro: jasne, to powinno działać – Liero

4

Różnica polega wirtualizacji UI (który WPF obsługuje wyjęciu z pudełka na różnym kontroli) w porównaniu do wirtualizacji danych (które WPF nie obsługuje z pudełko).

Sprowadza się do wirtualizacji interfejsu użytkownika, która renderuje tylko to, co jest potrzebne i widoczne; podczas gdy virtulizacja danych zatrzymuje tylko to, co może być potrzebne w danym momencie w pamięci.

Bea ma dwa świetne posty o numerach UI virtualization i data virtualization i omawia różnice i sposób obejścia ograniczeń związanych z brakiem obsługi wirtualizacji danych, która wydaje się być tym, na co masz ochotę.

Edycja:

Na 3,5 wsparcie SP1 wirtualizacji dodano TreeView. Być może wystarczy usunąć szablon ItemsPanel i wystarczy ustawić właściwości w TreeView.

+0

Rozumiem to. W moim pytaniu mówię o wirtualizacji UI, czemu nie rozumiem, dlaczego tworzy on kontener dla każdego z elementów 10001, mimo że wirtualność jest ustawiona na true. – Carlo

+0

@Carlos Dodano notatkę o usunięciu szablonu ItemsPanel; ponieważ uważam, że domyślnym szablonem od wersji 3.5 SP1 powinien być VirtualizingStackPanel, więc nie powinno być potrzeby zmiany szablonu, wystarczy włączyć właściwość tak, jak zrobiłeś to za pomocą TreeView. –

+0

Wypróbowałeś to, o czym wspomniałeś w swojej edycji. Nie działa też. Nadal mam do czynienia z tysiącem kontroli. To naprawdę dziwne. I nadal zdarzenie CleanUpVirtualizedItem nie zostaje uruchomione, co jest kolejną wskazówką, że wirtualizacja nie działa. – Carlo

2

To nie jest dokładne. To prawda, że ​​virtualuzation działa tylko z wiązaniem, jednak jak zaobserwowałem w niektórych przykładowych aplikacjach, recykling elementów występuje tylko na elementach root widoku drzewa.

, więc jeśli masz tylko 1 element główny z 1000 dzieci, nie będzie recyklingu, ponieważ istnieje tylko 1 pojemnik dostępny do recyklingu.

jeśli masz 100 elementów root, a każda z nich ma 100 dzieci, otrzymasz częściowy recykling, ponieważ tylko elementy root 100 zostaną poddane recyklingowi, ale inne 9900 elementów potomnych zostanie zapisanych w pamięci.

oczywiście problem staje się gorszy, jeśli poziom zagnieżdżenia drzewa jest większy niż 2 lub 3.

Nie wiem, czy istnieje rozwiązanie tego problemu.