title: Extremely slow population of ListBox using DataBinding
body: <p>I was previously using the code behind to manually add items to my ListBox, but it was terribly slow. I heard that data binding via XAML was the way to go, in terms of performance.</p>
  
  <p>So I managed to get the data binding working (new to binding), but to my dismay, the performance is no better than my previous non-data binding method.</p>
  
  <p>The idea is that my ListBox contains an Image with a name below it. I did some benchmarking and 54 items take a full 8 seconds to display. Which naturally is too long for a user to wait.</p>
  
  <p>The source images are at a maxiumum: 2100x1535px and range from 400kb>4mb per file.</p>
  
  <p>The images required to reproduce this issue can be found here: Link removed as question has been answered and my server doesn't have very much bandwidth allowance. Other image source here: <a href="https://imgur.com/a/jmbv6" rel="nofollow noreferrer">https://imgur.com/a/jmbv6</a></p>
  
  <p>I've made a reproducible example of the issue below. What am I doing wrong that is making this so slow?</p>
  
  <p>Thank you.</p>
  
  <p>The XAML:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;Window x:Class="WpfApplication1.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
          xmlns:local="clr-namespace:WpfApplication1"
          mc:Ignorable="d"
          Title="MainWindow" Height="600" Width="800" WindowState="Maximized"&gt;
      &lt;Grid&gt;
          &lt;ListBox x:Name="listBoxItems" ItemsSource="{Binding ItemsCollection}"
                      ScrollViewer.HorizontalScrollBarVisibility="Disabled"&gt;
  
              &lt;ListBox.ItemsPanel&gt;
                  &lt;ItemsPanelTemplate&gt;
                      &lt;WrapPanel IsItemsHost="True" /&gt;
                  &lt;/ItemsPanelTemplate&gt;
              &lt;/ListBox.ItemsPanel&gt;
  
              &lt;ListBox.ItemTemplate&gt;
                  &lt;DataTemplate&gt;
                      &lt;VirtualizingStackPanel&gt;
                          &lt;Image Width="278" Height="178"&gt;
                              &lt;Image.Source&gt;
                                  &lt;BitmapImage DecodePixelWidth="278" UriSource="{Binding ImagePath}" CreateOptions="IgnoreColorProfile" /&gt;
                              &lt;/Image.Source&gt;
                          &lt;/Image&gt;
                          &lt;TextBlock Text="{Binding Name}" FontSize="16" VerticalAlignment="Bottom" HorizontalAlignment="Center" /&gt;
                      &lt;/VirtualizingStackPanel&gt;
                  &lt;/DataTemplate&gt;
              &lt;/ListBox.ItemTemplate&gt;
          &lt;/ListBox&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>The code behind:</p>
  
  <pre class="lang-cs prettyprint-override"><code>using System;
  using System.Collections.Generic;
  using System.Collections.ObjectModel;
  using System.ComponentModel;
  using System.Linq;
  using System.Windows;
  using System.Windows.Threading;
  
  namespace WpfApplication1
  {
      /// &lt;summary&gt;
      /// Interaction logic for MainWindow.xaml
      /// &lt;/summary&gt;
      public partial class MainWindow : Window
      {
          internal class Item : INotifyPropertyChanged
          {
              public Item(string name = null)
              {
                  this.Name = name;
              }
  
              public string Name { get; set; }
              public string ImagePath { get; set; }
  
              public event PropertyChangedEventHandler PropertyChanged;
              private void NotifyPropertyChanged(String propertyName)
              {
                  if (PropertyChanged != null)
                  {
                      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                  }
              }
          }
  
          ObservableCollection&lt;Item&gt; ItemsCollection;
          List&lt;Item&gt; data;
  
          public MainWindow()
          {
              InitializeComponent();
  
              this.data = new List&lt;Item&gt;();
              this.ItemsCollection = new ObservableCollection&lt;Item&gt;();
              this.listBoxItems.ItemsSource = this.ItemsCollection;
  
              for (int i = 0; i &lt; 49; i ++)
              {
                  Item newItem = new Item
                  {
                      ImagePath = String.Format(@"Images/{0}.jpg", i + 1),
                      Name = "Item: " + i
                  };
  
                  this.data.Add(newItem);
              }
  
              foreach (var item in this.data.Select((value, i) =&gt; new { i, value }))
              {
                  Dispatcher.Invoke(new Action(() =&gt;
                  {
                      this.ItemsCollection.Add(item.value);
                  }), DispatcherPriority.Background);
              }
          }
      }
  }
  </code></pre>