How to properly improve the loading of ItemsControl and avoid freezing

I am wondering if this is the right way to improve my loading of ItemsControl. I want to show elements that are quite heavy to load (due to complex XAML) and I don't want my WPF app to hang. I want my objects to be displayed after rendering and to be able to interact with other elements of my window at the same time (even if it's a little slower). Here are some suggestions to get you started:

  • Let's say that I cannot improve the load times of my products;
  • I cannot use virtualization because I need to see all my items at once;
  • The view does not wait for the background operation to complete; all work is done on the UI thread.

I managed to find a workaround, but I'm not happy with it, using BackgroundWorker

and sleep:

enter image description here

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:local="clr-namespace:WpfApplication1">
    <DockPanel>
        <Button DockPanel.Dock="Bottom" Content="Click me" Click="OnButtonClick"/>

        <ItemsControl ItemsSource="{Binding Items}">
            <!-- Items begin to be loaded once the ItemsControl is loaded -->
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Loaded">
                    <i:InvokeCommandAction Command="{Binding LoadCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border Width="25" Height="25" Background="Red" Margin="5">
                        <local:HeavyItem Content="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DockPanel>
</Window>

      

ViewModel.cs

public class ViewModel
{
    public ICommand LoadCommand { get; protected set; }

    public ObservableCollection<int> Items { get; protected set; }

    public ViewModel()
    {
        Items = new ObservableCollection<int>();
        LoadCommand = new DelegateCommand(AsyncLoad);
        //Load();
    }

    protected void Load()
    {
        for (int i = 0; i < 250; i++)
        {
            Items.Add(i);
        }
    }

    protected void AsyncLoad()
    {
        var bk = new BackgroundWorker();
        bk.DoWork += (s, e) =>
        {
            for (int i = 0; i < 250; i++)
            {
                // Sleep 50ms to let the UI thread breeze
                Thread.Sleep(50);
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Render, (Action)(() =>
                {
                    Items.Add(i);
                }));
            }
        };
        bk.RunWorkerAsync();
    }
}

      

HeavyItem.cs (fake control for heavy visual simulation)

public class HeavyItem : ContentControl
{
    protected override Size ArrangeOverride(Size finalSize)
    {
        Thread.Sleep(20);
        return base.ArrangeOverride(finalSize);
    }
}

      

This question suggests a similar approach. I don't like this method because:

  • The ViewModel does what the view should do;
  • I use a random timer while the element may take longer or less time to render depending on the computer.

I think the best way to do this is to override the ItemsControl and tell the UI thread to update after the item is added, but I was not successful. Any hint or ideas?

+3


source to share


1 answer


use CollectionView.DeferRefresh () to get one update?



https://blogs.msdn.microsoft.com/matt/2008/08/28/collectionview-deferrefresh-my-new-best-friend/

0


source







All Articles