2

レンダリングには高価なアイテムがたくさんあるリストボックスがあります。しかし、VirtualizingStackPanelは可視アイテムをレンダリングするだけでそれを処理します。私はScrollViewerのコントロールテンプレートをオーバーライドする必要があります。デフォルトのものは、水平スクロールバーと垂直スクロールバーの間に灰色の矩形があるからです。私はちょうど灰色の長方形の問題がないMicrosoft(ScrollViewer ControlTemplate Example)によって提供されたものをコピーしました。ScrollViewerの既定のコントロールテンプレートをオーバーライドすると、VirtualizingStackPanelが機能しなくなる

しかし、このコントロールテンプレートは、VirtualizingStackPanelの無限の高さを与えることによって仮想化を無効にします。つまり、VirtualizingStackPanelはすべてのアイテムを表示します。これは、すべてのアイテムが表示されていると考えているからです。

以下のデモコードでは、リストボックスに10000個のアイテムが表示されます。私はそれをScrollViewerスタイルと比較することで問題を検証します。デモが非常に遅く実行されると、リサイズには数秒かかります。スタイルがなければとても速いです。

ViewportHeight:8
ExtentHeight:10000
ActualHeight:245
(XAMLでスタイルをコメントアウト)ScrollViewerのスタイルがなければ

:I出力VirtualizingStackPanelに関するいくつかの情報は、私のポイントを証明するために 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> 

コードの背後にある:

このScrollViewerのスタイルをブレンド4からコピーされ、それが出力ウィンドウによさそうだ
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

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}"。仮想化が私のために再び働き始めると付け加えます。ありがとう。 –