2017-01-04 3 views
1

Когда у меня есть следующий TreeView в XAML (ItemsSource устанавливаются с помощью кода за длинный список списков списков):TreeView теряет виртуализацию с перегруженным шаблоном управления

<TreeView x:Name="Tree" 
      VirtualizingPanel.IsVirtualizing="True" 
      ScrollViewer.CanContentScroll="True"> 
    <!-- ItemTemplate and ItemContainerStyle ommitted for brevity --> 
</TreeView> 

виртуализация работает просто отлично. Однако, когда я попытался переопределить шаблон TreeView вместе с внутренним шаблоном ScrollViewer, виртуализация исчезла. Мой шаблон кажется идентичным по умолчанию, за исключением цветного прямоугольника, который я вынул, что было всей мотивацией для переопределения шаблона.

<TreeView.Template> 
     <ControlTemplate TargetType="{x:Type TreeView}"> 
      <ScrollViewer Focusable="False" 
          CanContentScroll="True"> 
       <ScrollViewer.Template> 
        <ControlTemplate TargetType="{x:Type ScrollViewer}"> 
         <Grid> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition Height="auto" /> 
          </Grid.RowDefinitions> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition /> 
           <ColumnDefinition Width="auto" /> 
          </Grid.ColumnDefinitions> 

          <ScrollContentPresenter Grid.Column="0" Grid.Row="0" /> 

          <ScrollBar x:Name="PART_VerticalScrollBar" 
             Orientation="Vertical" 
             Grid.Row="0" Grid.Column="1" 
             Value="{TemplateBinding VerticalOffset}" 
             Maximum="{TemplateBinding ScrollableHeight}" 
             ViewportSize="{TemplateBinding ViewportHeight}" 
             Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" /> 

          <ScrollBar x:Name="PART_HorizontalScrollBar" 
             Orientation="Horizontal" 
             Grid.Row="1" Grid.Column="0" 
             Value="{TemplateBinding HorizontalOffset}" 
             Maximum="{TemplateBinding ScrollableWidth}" 
             ViewportSize="{TemplateBinding ViewportWidth}" 
             Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" /> 
         </Grid> 
        </ControlTemplate> 
       </ScrollViewer.Template> 
       <ScrollViewer.Content> 
        <ItemsPresenter x:Name="ItemsPresenter" /> 
       </ScrollViewer.Content> 
      </ScrollViewer> 
     </ControlTemplate> 

Я временно удосужился это, просто сделать прозрачной SolidColorBrush названием {x:Static SystemColors.ControlBrushKey} в ресурсах TreeView, но я бы предпочел, чтобы знать, что я сделал неправильно.

ответ

0

Я нашел проблему. В шаблоне ScrollViewerScrollContentPresenter должен иметь значение CanContentScroll, установленное в его значение шаблона родителя.

<ScrollContentPresenter Grid.Column="0" Grid.Row="0" 
         CanContentScroll="{TemplateBinding CanContentScroll}" /> 
0

Ряд факторов могут привести к поломке виртуализации пользовательского интерфейса, иногда, когда вы не ожидаете его:

  1. Введения списка своего контроля в ScrollViewer: ScrollViewer обеспечивает окно на его содержания ребенка. Проблема в том, что детскому контенту предоставляется неограниченное «виртуальное» пространство . В этом виртуальном пространстве ListBox отображается в полном размере со всеми его дочерними элементами . В качестве побочного эффекта каждый элемент получает свою собственную память-hogging Объект ListBoxItem. Эта проблема возникает, когда вы помещаете ListBox в контейнер , который не пытается ограничить его размер; например, одна и та же проблема возникает, если вы вставляете ее в StackPanel вместо Grid.
  2. Изменение шаблона управления списком и невозможность использования ItemsPresenter: ItemsPresenter использует ItemPanelTemplate, который указывает VirtualizingStackPanel. Если вы нарушаете это отношение или если вы сами меняете ItemsPanelTemplate, чтобы он не использовал VirtualizingStackPanel, вы потеряете функцию виртуализации.
  3. Не использовать привязку данных: это должно быть очевидно, но если вы программным образом заполните список - , путем динамического создания объектов ListBoxItem, которые вам нужны, - не будет виртуализации . Разумеется, вы можете использовать свою собственную оптимизацию стратегии, например, создавать только те объекты, которые вам нужны, и создавать их только по адресу , когда они понадобятся.
+0

# 1 похоже, что это может быть актуально, но я не уверен, как я могу это решить. Я попытался установить высоту ScrollViewer на {{TemplateBinding Height}} (и то же самое для сетки внутри ScrollViewer), но не повезло. Что касается № 2, я использовал ItemPresenter (как вы можете видеть) и даже попытался явно установить ItemPanelTemplate, как предлагал @ d.moncada, но все равно не повезло. Я должен не согласиться с № 3; Я могу ясно видеть разницу с виртуализацией и без нее, даже когда ProductSource генерируется программно. Окно даже не загружается, когда виртуализация отключена. –