问题
Background
I have a custom control that inherits from a TreeView and is modified to display in a data grid style. The problem I am seeing is with performance when expanding the tree. This is common from my research with Tree Views. Upon inspection with the WPF Performance tools I noticed that the ItemsPresenter class is using a regular Stack Panel instead of a Virtualizing Stack Panel.
Here is the section of code where the ScrollContentPresenter is used (showing in image).
<ScrollContentPresenter Name="PART_ScrollContentPresenter"
KeyboardNavigation.DirectionalNavigation="Local"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CanContentScroll="{TemplateBinding CanContentScroll}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
Here is the template being passed in.
<ControlTemplate TargetType="CommonControls:TreeListViewItem508">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border x:Name="item">
<Border Name="InnerBorder">
<Grid Style="{StaticResource GridBackgroundStyle}">
<Rectangle Visibility="Collapsed" Fill="#75FFFFFF" Name="UpperHighlight" />
</Grid>
</Border>
</Border>
<ItemsPresenter Grid.Row="1" Name="ItemsHost" />
</Grid>
</ControlTemplate>
Question
Is it possible to force the items presenter to use a virtualizing stack panel?
Notes
- I have already tried wrapping the ItemsPresenter in a ScrollViewer but that gives undesired results (scroll bars for each row).
- I hard coded the option CanContentScroll = true as a test since this disables virtualization when its set to false.
- This control is in production and used in multiple places so I don't have the option to replace / rewrite / or perform major modifications to the design at this point. I am just looking to override this one section if possible.
Any suggestions or options are much appreciated.
Resolved:
I modified the template's style by adding this to the style and it switched the stack panels to virtualizing.
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
回答1:
Try
<TreeView>
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
or
<TreeView VirtualizingStackPanel.IsVirtualizing="True">
Obviosuly replace TreeView, with your treeview control name.
Hope that helps
Paul
回答2:
You can use a VirtualizingStackPanel
, however be aware that there is more to virtualizing a StackPanel than just using a VirtualizingStackPanel
Here is an example using the code found in the link posted above which lists the items that are needed:
<ItemsControl ...
VirtualizingStackPanel.IsVirtualizing="True" <!-- this is needed -->
ScrollViewer.CanContentScroll="True" > <!-- this is needed -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel /> <!-- this is needed -->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border ...>
<ScrollViewer> <!-- this is needed -->
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
来源:https://stackoverflow.com/questions/9503433/is-it-possible-to-override-the-itemspresenter-to-use-a-virtualizing-stackpanel-i