I'm building a search function for my application where the list of matching products should update at every keystroke, but it's way too slow and the strange things is that the actual update time in the GUI is much longer than the time it takes to retrieve the matching products from the database.
To avoid slow scrolling in the list, I'm using virtualization as described here: http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization, scrolling now works pretty smoothly, but updating the list takes many seconds for about 30000 products, it's equally slow when writing the 4:th letter (then generating <100 products) as when writing the first.
The code is similar to the codeproject one, XAML:
<ListView Grid.Row="7" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="2" Style="{DynamicResource lvStyle}"/>
<Style x:Key="lvStyle" TargetType="{x:Type ListView}">
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling"/>
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="True"/> <!-- Todo was originally true -->
<Setter Property="ListView.ItemsSource" Value="{Binding ProductNames}"/>
<Setter Property="ListView.View">
<Setter.Value>
<GridView>
<GridViewColumn Header="Id" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProductID}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</Setter.Value>
</Setter>
<!-- <Style.Triggers>
<DataTrigger Binding="{Binding IsLoading}" Value="True">
<Setter Property="ListView.Cursor" Value="Wait"/>
<Setter Property="ListView.Background" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>-->
</Style>
ViewModel:
private VirtualizingCollection<ProductName> productNames;
public VirtualizingCollection<ProductName> ProductNames
{
get
{
if(productNames == null)
productNames = new VirtualizingCollection<ProductName>(new ProductNameProvider(ProductNamesQuery()),100);
return productNames;
}
}
My ProductNameProvider:
public class ProductNameProvider : IItemsProvider<Models.ProductName>
{
private IQueryable<Models.ProductName> _query;
public ProductNameProvider(IQueryable<Models.ProductName> query )
{
_query = query;
}
public int FetchCount()
{
return _query.Count();
}
public IList<Models.ProductName> FetchRange(int startIndex, int count)
{
return _query.Skip(startIndex).Take(count).ToList();
}
}
The only code I've managed to measure is the one in the viewmodel, and I know that's fast enough, is there a way to measure and evaluate the rest of the time it takes to update the GUI?