Nicolas Zawada
Nicolas Zawada

Reputation: 507

Bad performance ListView in TabControl WPF

I have a TabControl with three TabItems. Each TabItem has its own ViewModel. The last tab contains a ListView with +1500 records. So every time I open this tab, it takes +-10 seconds to render. I want to optimize the ListView so it doesn't take that long to render every time.

I'm binding a ObservableCollection to the ListView.

The ListView looks like this

<ListView>
    <ListView.View>
        <GridView>
            <GridViewColumn>
                <GridViewColumnHeader>
                   <TextBox... custom templates for filtering here
                </GridViewColumnHeader>
            </GridViewColumn>
            </GridView>
    <ListView.View>
</ListView>

I've already tried:

<VirtualizingPanel.VirtualizationMode="Recycling">

This speeds it up, but makes scrolling reeeeeeeally slow.

Upvotes: 1

Views: 352

Answers (1)

Dmitry Polishuk
Dmitry Polishuk

Reputation: 196

I think you can separate your big collection on the few small pages (20/50 items) and add new items by a little. I can recommend you to use Behavior for refresh the page. Just bind awaitable command to add new items to the collection. New items will be adding while scrollig down.

internal class ScrollEndToCommandBehavior : Behavior<ScrollViewer>
{
    #region Public Static Fields and Constants

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof (object), typeof (ScrollEndToCommandBehavior), new PropertyMetadata(null));

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof (ICommand), typeof (ScrollEndToCommandBehavior), new PropertyMetadata(null));

    #endregion

    #region Public Properties

    public ICommand Command
    {
        get { return (ICommand) GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }


    public object CommandParameter
    {
        get { return GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    #endregion

    #region Protected Methods

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.ViewChanged += AssociatedObjectOnViewChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.ViewChanged -= AssociatedObjectOnViewChanged;
        base.OnDetaching();
    }

    #endregion

    #region Private Methods

    private void AssociatedObjectOnViewChanged(object sender, ScrollViewerViewChangedEventArgs eventArgs)
    {
        if (!eventArgs.IsIntermediate && Math.Abs(AssociatedObject.ScrollableHeight - AssociatedObject.VerticalOffset) < 5)
        {
            Command?.Execute(CommandParameter);
        }
    }

    #endregion
}

Upvotes: 1

Related Questions