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)?

Timothy Khouri
  • 31,315
  • 21
  • 88
  • 128
  • 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? – cdiggins Dec 07 '12 at 02:03

4 Answers4

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> 
  • That's both amazing and astonishing. Is there anyway to get the same look/feel of using GridView instead of DataTemplating things myself? – Timothy Khouri Nov 17 '08 at 20:05
  • Yes. Just put the " " part in your code. This is the part which speeds up things. –  Nov 17 '08 at 20:18
  • 5
    Note that VirtualizingStackPanels are the default items panel template for ListViews. Using some features like grouping will override the default, however. – scobi Jan 06 '10 at 22:24
  • 2
    You also want to make sure that ScrollViewer.CanContentScroll is NOT set to false or this will disable virtualisation (as inferred by scobi) – Rodney Thomson Jan 22 '16 at 06:28
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.

Tawani
  • 11,067
  • 20
  • 82
  • 106
5

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.

Simon Voggeneder
  • 377
  • 1
  • 7
  • 16
  • 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. – Mios Jan 20 '21 at 09:55
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>
Indy Singh
  • 27
  • 1
  • 5