WPF ListView Very Slow Performance - Why? (ElementHost, or Other Reason?)
Asked Answered
S

4

28

I have a Windows Forms app, that has a single ElementHost containing a WPF UserControl... in my WPF, I have a VERY simple ListView:

<ListView Margin="4" ItemsSource="{Binding Notifications}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding FirstName}" />
            <GridViewColumn Header="LastName" DisplayMemberBinding="{Binding LastName}" />
            <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}" />
            <GridViewColumn Header="City" DisplayMemberBinding="{Binding City}" />
            <GridViewColumn Header="State" DisplayMemberBinding="{Binding State}" />
            <GridViewColumn Header="Zip" DisplayMemberBinding="{Binding Zip}" />
        </GridView>
    </ListView.View>
</ListView>

If my source has 10 items, the form loads in less than one second. If my source has 1000 items, it takes 7 seconds!!! My timer is ONLY taking the loading into account (not how much time it takes to get the items).

So my question is:

Is using an ElementHost a performance nightmare?

Is WPF DataBinding a performance nightmare?

Is the ListView a piece of crap? (btw, same results with the WPFToolkit's DataGrid)?

Scary answered 17/11, 2008 at 19:9 Comment(1)
So I'll ask your question with an answer: do you think that using a WPF list-view out of the box as prescribed with 1000 items should consume 2GB of memory and take 7 seconds to load? Do you think that this is the result of good software engineering on behalf of the WPF designers?Stgermain
P
34

Use virtualization

<ListView ItemsSource="{BindingNames}"Name="lv">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                   <!--<StackPanel/>
                    If StackPanel was used, the memory consumed was over 2GB and dead slow.
                    -->
                   <VirtualizingStackPanel>
                    <!--Memory footprint is only 200 mb-->
                    </VirtualizingStackPanel>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView> 
Pikestaff answered 17/11, 2008 at 19:33 Comment(4)
That's both amazing and astonishing. Is there anyway to get the same look/feel of using GridView instead of DataTemplating things myself?Scary
Yes. Just put the "<ListView.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel/> </ItemsPanelTemplate> </ListView.ItemsPanel>" part in your code. This is the part which speeds up things.Am
Note that VirtualizingStackPanels are the default items panel template for ListViews. Using some features like grouping will override the default, however.Babbitt
You also want to make sure that ScrollViewer.CanContentScroll is NOT set to false or this will disable virtualisation (as inferred by scobi)Tamarin
J
12

You may also want to check this excellent article on the Code Project:

WPF: Data Virtualization By Paul McClean http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx

It show you a much better approach at minimal memory and bandwidth usage.

Julianajuliane answered 7/4, 2009 at 15:15 Comment(0)
A
6

I had a case where the answers presented here didn't solve my problem. In my case, setting the MaxHeight property of the ListView to a value larger than the actual displayed height solved it immediately, thanks to this answer here, even if I cannot explain how and why it worked.

Amatruda answered 16/1, 2019 at 8:10 Comment(1)
MaxHeight can be a game changer - especially for ListView that stretch parent's control hwight, like the last item in DockPanel. Setting fixed MaxHeight makes control fast, when before it was unusable.Wesla
H
0

I had the same problem. Replacing the listview with DataGrid containing DataGridTextColumn items fixed the problem.

<DataGrid Margin="4" ItemsSource="{Binding Notifications}">
    <DataGrid.Columns>
    <DataGridTextColumn Header="FirstName" DisplayMemberBinding="{Binding FirstName}" />
    <DataGridTextColumn Header="LastName" DisplayMemberBinding="{Binding LastName}" />
</DataGrid.Columns>
Haldas answered 10/3, 2023 at 3:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.