2

У меня есть список с большим количеством предметов, которые дорого переносятся. Однако VirtualizingStackPanel позаботится об этом, только визуализируя видимые элементы. Я хочу переопределить шаблон управления для ScrollViewer, поскольку по умолчанию у него серый прямоугольник между горизонтальной и вертикальной полосами прокрутки. Я просто скопировал файл, предоставленный Microsoft (ScrollViewer ControlTemplate Example), который не имеет проблемы с серым прямоугольником.VirtualizingStackPanel перестает работать при переопределении шаблона управления по умолчанию для ScrollViewer

Эта контрольная таблица, однако, отключает виртуализацию, предоставляя бесконечную высоту VirtualizationStackPanel. Это означает, что VirtualizingStackPanel будет отображать все элементы, поскольку он считает, что все элементы видны.

В приведенном ниже демо-коде я показываю 10000 элементов в списке. Я проверяю проблему, сравнивая ее с стилем ScrollViewer и без него. С ним демо работает очень медленно, изменение размера занимает много секунд. Без стиля это очень быстро. Я выход некоторую информацию о VirtualizingStackPanel, чтобы доказать свою точку зрения:

Без стиля ScrollViewer (Закомментируйте стиль в XAML):

ViewportHeight: 8
ExtentHeight: 10000
ActualHeight: 245
IsVirtualizing: Правда
VirtualizationMode: Стандартный

с стиле ScrollViewer:

ViewportHeight: 0
ExtentHeight: 0
ActualHeight: +272766,666666707
IsVirtualizing: Правда
VirtualizationMode: Стандартный

Любая идея, как написать шаблон управления для ScrollViewer, который не беспорядок с виртуализацией?

XAML: за

<Window x:Class="VirtualTest.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"> 

    <Window.Resources> 

     <Style x:Key="{x:Type ScrollViewer}" TargetType="{x:Type ScrollViewer}"> 
      <Setter Property="OverridesDefaultStyle" Value="true" /> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ScrollViewer}"> 
         <Grid> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition /> 
           <ColumnDefinition Width="Auto" /> 
          </Grid.ColumnDefinitions> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition Height="Auto" /> 
          </Grid.RowDefinitions> 
          <ScrollContentPresenter Grid.Row="0" Grid.Column="0" /> 
          <ScrollBar 
           Name="PART_VerticalScrollBar" 
           Grid.Row="0" Grid.Column="1" 
           Value="{TemplateBinding VerticalOffset}" 
           Maximum="{TemplateBinding ScrollableHeight}" 
           ViewportSize="{TemplateBinding ViewportHeight}" 
           Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" /> 
          <ScrollBar 
           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> 
       </Setter.Value> 
      </Setter> 
     </Style> 

    </Window.Resources> 

    <Grid> 
     <ListBox 
      ItemsSource="{Binding Numbers}" 
      ScrollViewer.ScrollChanged="ListBox_ScrollChanged" 
      Background="Orange"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Border BorderBrush="Red" BorderThickness="2" Margin="5"> 
         <TextBlock Text="{Binding .}" Width="400"/> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 

    </Grid> 
</Window> 

Код:

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 

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

      DataContext = this; 
     } 

     public IEnumerable<double> Numbers 
     { 
      get 
      { 
       for (int i = 0; i < 10000; i++) 
       { 
        yield return i; 
       } 
      } 
     } 

     private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e) 
     { 
      ListBox listBox = sender as ListBox; 
      VirtualizingStackPanel virtualizingStackPanel = FindVirtualizingStackPanel(listBox);        
      Debug.WriteLine("ViewportHeight: " + virtualizingStackPanel.ViewportHeight); 
      Debug.WriteLine("ExtentHeight: " + virtualizingStackPanel.ExtentHeight); 
      Debug.WriteLine("ActualHeight: " + virtualizingStackPanel.ActualHeight); 
      Debug.WriteLine("IsVirtualizing: " + VirtualizingStackPanel.GetIsVirtualizing(virtualizingStackPanel)); 
      Debug.WriteLine("VirtualizationMode: " + VirtualizingStackPanel.GetVirtualizationMode(virtualizingStackPanel)); 
     } 

     private VirtualizingStackPanel FindVirtualizingStackPanel(Visual visual) 
     { 
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++) 
      { 
       Visual child = VisualTreeHelper.GetChild(visual, i) as Visual; 

       if (child != null) 
       { 
        if (child is VirtualizingStackPanel) 
        { 
         return child as VirtualizingStackPanel; 
        } 

        VirtualizingStackPanel found = FindVirtualizingStackPanel(child); 
        if (found != null) 
        { 
         return found; 
        } 
       } 
      } 

      return null; 
     } 
    } 
} 

ответ

3

Этот ScrollViewer стиль копируется из Blend, 4 и он хорошо выглядит в окне вывода

ViewportHeight: 10
ExtentHeight: 10000
Закон ualHeight: 308
IsVirtualizing: Правда
VirtualizationMode: Стандартный

<Style TargetType="{x:Type ScrollViewer}"> 
    <Style.Triggers> 
     <Trigger Property="IsEnabled" Value="false"> 
      <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> 
     </Trigger> 
    </Style.Triggers> 
    <Setter Property="Template" Value="{DynamicResource ScrollViewerControlTemplate1}"/> 
</Style> 
<ControlTemplate x:Key="ScrollViewerControlTemplate1" TargetType="{x:Type ScrollViewer}"> 
    <Grid x:Name="Grid" Background="{TemplateBinding Background}"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/> 
     <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/> 
     <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/> 
     <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/> 
    </Grid> 
</ControlTemplate> 
+1

Спасибо, что стиль имеет виртуализация работает. Они фактически устанавливают кисть заливки прямоугольника в SystemColors.ControlBrushKey, почему бы просто не сделать ее прозрачной? То, что отсутствовало в моем стиле, было в определении ScrollContentPresenter: CanContentScroll = "{TemplateBinding CanContentScroll}". Если я добавлю, что виртуализация снова начнет работать для меня. Благодарю. –