I'm trying to load a rather big list of items into an WPF DataGrid. Problem is: It's painfully slow. Right now I have about 20,000 items in my list and it takes forever (well ... in my latest version it takes about 10 seconds, but that's not nearly good enough). Im working on it for the last couple of days, but I don't find a solution that is really working.
1) Of course UI virtualization is enabled (that is not the problem anymore)
2) I also tried some solution as described by Bea Stollnitz here and others. These solutions are great, but do not work for me since my collection has to be updated, filtered and sorted at runtime without reloading the collection. The solutions I found are only working with IList implementations ... I need a Observable collection to keep my items up to date.
This is the situation: I do have a Observable collection of my domain data obejcts (it's updated via WCF asychrously). I do have a ViewModel for the list items wrapping the domain objects. When I open the view I have a second list that will get populated with an ViewModel instance for each domain object. An THAT is the real problem. Since the "target" collection is bound to my DataGrid, I have to dispatch the creation of the ViewModels into the UI thread (otherwise .Net is not very happy about the collection change from another thread). So I am polluting the Dispatcher queue with 20,000 view model creation calls. Creating a ViewModel is pretty cheap, but I still have 20,000 calls in the dispatcher queue and at the same time the DataGrid is demanding CPU in the same thread to fill itself.
My idea (not quite finished): Since I already have UI virtualization in place, I would like to create the ViewModels NOT when I open my view, but on the fly then I need them. When the user can see the first 20 entries initially I only need to create 20 ViewModels and not 20,000. And here is my problem: I have no idea how. That's where you come in :)
I would like to have something like this (not working that way .. just to show what I mean):
<DataGrid ItemsSource={Binding MyDomainOjectCollection}>
<DataGrid.RowStyle>
<Style>
<Setter Property="DataContext"
Value="{Binding DataContext,
Converter={StaticResource MyViewModelFactoryConverter}}">
</Setter>
</Style>
</DataGrid.RowStyle>
</DataGrid>
It does not have to be a Converter, it can also be something else or be done in code behind. I don't care. All I need is: Bind directly to the DomainObject collection, create the corresponding ViewModels on the fly and use the just created ViewModel instead of the original object to fill a single row. Any ideas?