9

I'm using .NET 4.5/VS2012, and I have a ListView looks something like this

<ListView 
    VirtualizingPanel.IsContainerVirtualizable="True"
    VirtualizingPanel.IsVirtualizing="True"
    VirtualizingPanel.IsVirtualizingWhenGrouping="True"
    Grid.Row="1"
    Name="eventLogList"
    Margin="5,0,5,0"
    BorderBrush="Black"
    BorderThickness="2"
    ItemsSource="{Binding EventLogs}"
    SelectedItem="{Binding SelectedEventLog}"
    local:ListViewSorter.CustomListViewSorter="EventLogViewer.UI.EventLogItemComparer"
    SelectionMode="Single">

    <ListView.GroupStyle>
        <GroupStyle HidesIfEmpty="False">
            <GroupStyle.ContainerStyle>
                <Style TargetType="GroupItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="GroupItem">
                                <Expander IsExpanded="True">
                                    <Expander.Header>
                                        <TextBlock FontSize="20" TextWrapping="Wrap" Margin="0,10,0,5" >
                                        <Bold><TextBlock Text="{Binding Name}"/></Bold> - <TextBlock FontSize="20" Text="{Binding ItemCount}"/> logs
                                    </TextBlock>
                                    </Expander.Header>
                                    <ItemsPresenter/>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </ListView.GroupStyle>
    <ListView.View>
        <GridView>
            <GridViewColumn 
                Header="event id"
                Width="120"
                DisplayMemberBinding="{Binding EventID}" />
            <GridViewColumn 
                Header="level"
                Width="160"
                DisplayMemberBinding="{Binding Level}" />
            <GridViewColumn 
                Header="server" 
                Width="160"
                DisplayMemberBinding="{Binding Server}" />
            <GridViewColumn 
                Header="log name" 
                Width="160"
                DisplayMemberBinding="{Binding LogName}" />
            <GridViewColumn 
                Header="source"
                Width="240"
                DisplayMemberBinding="{Binding Source}" />
            <GridViewColumn 
                Header="logged"
                Width="240"
                DisplayMemberBinding="{Binding Logged}" />
        </GridView>
    </ListView.View>
</ListView>

But still the performance is not improving at all. I found an example using ListBox, but how to virtualize a ListView? I struggled quite a bit. I heard that with grouping, the virtualization is turned off in previous version of WPF, but with .NET 4.5, WPF has a IsVirtualizingWhenGrouping property, I already set it to True.

Update: The culprit is custom styling, after removing it, the list view runs smoothly like butter

imgen
  • 2,803
  • 7
  • 44
  • 64

3 Answers3

16

"UI virtualization stores only visible items in memory but in a data-binding scenario stores the entire data structure in memory. In contrast, data virtualization stores only the data items that are visible on the screen in memory."

"By default, UI virtualization is enabled for the ListView and ListBox controls when their list items are bound to data."

For more info view the original MSDN source.

omerts
  • 8,485
  • 2
  • 32
  • 39
Kalin Krastev
  • 552
  • 6
  • 19
6

This article will help you a lot.Also can see..

Community
  • 1
  • 1
ridoy
  • 6,274
  • 2
  • 29
  • 60
  • 1
    Second link is not helping much since I'm budget tight and cannot afford to use commercial one, as for the MSDN discussion, I'm still digesting, I did use some custom style, will try to disable them to test. – imgen Jan 22 '13 at 15:14
  • 2
    After disabling custom style, the issue is resolved. Looking for a way to get the best of both worlds though. – imgen Jan 23 '13 at 15:28
5

I know this is an old question but I came across it looking for an answer to my question and wanted to share what I discovered in case it's useful for anyone else. I had a very similar situation with a ListView control that was not virtualizing. I remove the custom style that I had on it (after reading this thread and associated links) and it started virtualizing correctly.

After much investigation, comparison to the default template, and narrowing down I figure out that it was the 'CanContentScroll' property on the ScrollContentPresenter inside that template. I had not set it at all, and when I set it to true it started virtualizing properly. I also noticed that the default template had 'CanHorizontallyScroll="False"' and 'CanVerticallyScroll="False"'; those didn't seem to make a difference that I could tell in my limited testing (I'm sure someone can chime in and say what they do) but I left them in anyway.

Here is my final style (note that this was started from default and modified, so not sure where the CanContentScroll property got dropped...):

<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}"
   TargetType="ScrollViewer">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ScrollViewer">
                <Grid Background="{TemplateBinding Background}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <DockPanel Margin="{TemplateBinding Padding}">
                        <ScrollViewer DockPanel.Dock="Top"
                                      HorizontalScrollBarVisibility="Hidden"
                                      VerticalScrollBarVisibility="Hidden"
                                      Focusable="false">
                            <GridViewHeaderRowPresenter Margin="2,0,2,0"
                                                        Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
            ColumnHeaderContainerStyle="{Binding
                         Path=TemplatedParent.View.ColumnHeaderContainerStyle,
                         RelativeSource={RelativeSource TemplatedParent}}"
            ColumnHeaderTemplate="{Binding
                         Path=TemplatedParent.View.ColumnHeaderTemplate,
                         RelativeSource={RelativeSource TemplatedParent}}"
            ColumnHeaderTemplateSelector="{Binding 
                         Path=TemplatedParent.View.ColumnHeaderTemplateSelector,
                         RelativeSource={RelativeSource TemplatedParent}}"
            AllowsColumnReorder="{Binding
                         Path=TemplatedParent.View.AllowsColumnReorder,
                         RelativeSource={RelativeSource TemplatedParent}}"
            ColumnHeaderContextMenu="{Binding
                         Path=TemplatedParent.View.ColumnHeaderContextMenu,
                         RelativeSource={RelativeSource TemplatedParent}}"
            ColumnHeaderToolTip="{Binding
                         Path=TemplatedParent.View.ColumnHeaderToolTip,
                         RelativeSource={RelativeSource TemplatedParent}}"
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </ScrollViewer>

                        <ScrollContentPresenter Name="PART_ScrollContentPresenter"
                                                KeyboardNavigation.DirectionalNavigation="Local" 
                                                CanContentScroll="True"
                                                CanHorizontallyScroll="False"
                                                CanVerticallyScroll="False"/>
                    </DockPanel>

                    <ScrollBar Name="PART_HorizontalScrollBar"
                               Orientation="Horizontal"
                               Grid.Row="1"
                               Maximum="{TemplateBinding ScrollableWidth}"
                               ViewportSize="{TemplateBinding ViewportWidth}"
                               Value="{TemplateBinding HorizontalOffset}" 
                               Style="{StaticResource StScrollBarNoMargin}"
                               Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                    <ScrollBar Name="PART_VerticalScrollBar"
                               Grid.Column="1"
                               Style="{StaticResource StScrollBarNoMargin}"
                               Maximum="{TemplateBinding ScrollableHeight}"
                               ViewportSize="{TemplateBinding ViewportHeight}"
                               Value="{TemplateBinding VerticalOffset}"
                               Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
sfaust
  • 2,089
  • 28
  • 54