2

Ich habe ein Listenfeld mit vielen Elementen, deren Wiedergabe teuer ist. Das VirtualizingStackPanel kümmert sich jedoch darum, indem nur die sichtbaren Elemente gerendert werden. Ich möchte die Steuerungsvorlage für ScrollViewer außer Kraft setzen, da die Standardvorlage ein graues Rechteck zwischen der horizontalen und vertikalen Bildlaufleiste aufweist. Ich habe nur die von Microsoft (ScrollViewer ControlTemplate Example), die nicht das Problem mit dem grauen Rechteck haben, zur Verfügung gestellt.VirtualizationStackPanel funktioniert nicht mehr beim Überschreiben der Standardsteuerelementvorlage für ScrollViewer

Diese Steuerungstemplate deaktiviert jedoch die Virtualisierung, indem sie dem VirtualizingStackPanel endlose Höhe gibt. Das bedeutet, dass das VirtualizingStackPanel alle Elemente rendert, da es alle Elemente für sichtbar hält.

In der folgenden Demo-Code zeige ich 10000 Elemente in einer Listbox. Ich verifiziere das Problem, indem ich es mit dem ScrollViewer-Stil und ohne es vergleiche. Damit läuft das Demo sehr langsam, die Größenänderung dauert viele Sekunden. Ohne den Stil ist es sehr schnell. I-Ausgang einige Informationen über den VirtualizingStackPanel meinen Punkt zu beweisen:

Ohne den Scroll Stil (den Stil in den XAML Kommentar out):

Viewportheight: 8
ExtentHeight: 10000
Actual: 245
IsVirtualizing: Wahr
VirtualizationMode: Standard

Mit dem Scroll Stil:

Viewportheight: 0
ExtentHeight: 0
Actual: 272766,666666707
IsVirtualizing: Wahre
VirtualizationMode: Standard

Jede Idee, wie eine Steuer Vorlage für einen Scroll zu schreiben, die nicht Chaos mit Virtualisierung?

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> 

-Code hinter:

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; 
     } 
    } 
} 

Antwort

3

Dieser Scroll Stil von Blend 4 kopiert und es sieht gut aus im Ausgabefenster

Viewportheight: 10
AusdehnungHöhe: 10000
Act ualHeight: 308
IsVirtualizing: Wahre
VirtualizationMode: Standard

<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

Danke, das Stil hat Virtualisierung arbeiten. Sie setzen den Rechteck-Füllpinsel tatsächlich auf SystemColors.ControlBrushKey, warum nicht einfach transparent machen? Was in meinem Stil fehlte, war in der Definition von ScrollContentPresenter: CanContentScroll = "{TemplateBinding CanContentScroll}". Wenn ich hinzufügen, dass die Virtualisierung für mich wieder funktioniert. Vielen Dank. –

Verwandte Themen