title: treeview getting very slow when worked on for a couple of minutes
body: <p>as mentioned in the title, i have a big number of items in a hierarchical structure, i want to display them in a treeview control, besides the load time, at the start the performance is not bad, but the longer one works with the treeview (checking the checkboxes, expanding, contracting, selecting) the slower it gets, here is the example code (the number of elements are chosen in such a manner, that they represent a realistic maximum number of elements for normal usage, if you run out of memory just adjust the number of created items)</p>
  
  <p>XAML Code:</p>
  
  <pre><code>&lt;Window x:Class="testLargeContourTree.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="MainWindow" Height="350" Width="525"&gt;
      &lt;Grid&gt;
          &lt;Grid.ColumnDefinitions&gt;
              &lt;ColumnDefinition Width="*" /&gt;
              &lt;ColumnDefinition Width="*" /&gt;
          &lt;/Grid.ColumnDefinitions&gt;
          &lt;Grid Grid.Column="0"&gt;
              &lt;Grid.RowDefinitions&gt;
                  &lt;RowDefinition Height="*" /&gt;
                  &lt;RowDefinition Height="Auto" /&gt;
                  &lt;RowDefinition Height="Auto" /&gt;
                  &lt;RowDefinition Height="Auto" /&gt;
                  &lt;RowDefinition Height="Auto" /&gt;
              &lt;/Grid.RowDefinitions&gt;
              &lt;TreeView  Grid.Row="0" x:Name="treeView" ItemsSource="{Binding Children}"&gt;
                  &lt;!--&lt;TreeView.Resources&gt;
                      &lt;Style TargetType="TreeViewItem"&gt;
                          &lt;Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /&gt;
                          &lt;Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /&gt;
                      &lt;/Style&gt;
                  &lt;/TreeView.Resources&gt;--&gt;
                  &lt;TreeView.ItemTemplate&gt;
                      &lt;HierarchicalDataTemplate ItemsSource="{Binding Children}"&gt;
                          &lt;StackPanel Orientation="Horizontal"&gt;
                              &lt;CheckBox IsChecked="{Binding IsChecked}" /&gt;
                              &lt;TextBlock Text="{Binding Name}" /&gt;
                          &lt;/StackPanel&gt;                  
                      &lt;/HierarchicalDataTemplate&gt;
                  &lt;/TreeView.ItemTemplate&gt;
              &lt;/TreeView&gt;
              &lt;Button Grid.Row="1" Content="Start" /&gt;
              &lt;Button Grid.Row="2" Content="Stop" /&gt;
              &lt;Button Grid.Row="3" Content="Move Up" /&gt;
              &lt;Button Grid.Row="4" Content="Move Down" /&gt;
          &lt;/Grid&gt;
          &lt;TextBlock Grid.Column="1" x:Name="textOut" /&gt;
      &lt;/Grid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>C# Code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Windows;
  using System.Windows.Controls;
  using System.Windows.Data;
  using System.Windows.Documents;
  using System.Windows.Input;
  using System.Windows.Media;
  using System.Windows.Media.Imaging;
  using System.Windows.Navigation;
  using System.Windows.Shapes;
  using System.Collections.ObjectModel;
  using System.ComponentModel;
  using System.Threading;
  using System.Windows.Threading;
  
  
  namespace testLargeContourTree
  {
      /// &lt;summary&gt;
      /// Interaktionslogik für MainWindow.xaml
      /// &lt;/summary&gt;
      public partial class MainWindow : Window
      {
          private MyTreeViewItem _itemCollection;
  
          public MainWindow()
          {
              InitializeComponent();
  
              _itemCollection = new MyTreeViewItem();
              MyTreeViewItem year;
              MyTreeViewItem month;
              MyTreeViewItem day;
              MyTreeViewItem job;
              MyTreeViewItem contour;
              MyTreeViewItem segment;
              Int32 numberOfJobs = 0;
              Int32 numberOfSegments = 0;
              for (Int32 i = 0; i &lt; 2; i++)
              {
                  year = new MyTreeViewItem(String.Format("{0}", 2013 + i));
                  for (Int32 j = 0; j &lt; 12; j++)
                  {
                      month = new MyTreeViewItem(String.Format("{0}", (Months)j));
                      for (Int32 k = 0; k &lt; 10; k++)
                      {
                          day = new MyTreeViewItem(String.Format("{0}", k + 1));
                          for (Int32 l = 0; l &lt; 20; l++)
                          {
                              job = new MyTreeViewItem(String.Format("Job {0}", numberOfJobs + 1));
                              for (Int32 m = 0; m &lt; 50; m++)
                              {
                                  contour = new MyTreeViewItem(String.Format("Contour {0}", m + 1));
                                  for (Int32 n = 0; n &lt; 100; n++)
                                  {
                                      segment = new MyTreeViewItem(String.Format("Segment {0}", n + 1));
                                      contour.AddChild(segment);
                                      numberOfSegments++;
                                  }
                                  job.AddChild(contour);
                              }
                              day.AddChild(job);
                              numberOfJobs++;
                          }
                          month.AddChild(day);
                      }
                      year.AddChild(month);
                  }
                  _itemCollection.AddChild(year);
              }
              treeView.DataContext = _itemCollection;
              textOut.Text = String.Format("number of segments: {0}", numberOfSegments + 1);
          }
      }
  
      public enum Months
      {
          Jannuary,
          February,
          March,
          April,
          May,
          June,
          July,
          August,
          September,
          October,
          November,
          December
      }
  
  
      public class MyTreeViewItem : INotifyPropertyChanged
      {
          private String _name;
          public String Name
          {
              get { return _name; }
              set { _name = value; OnPropertyChanged("Name"); }
          }
          public ObservableCollection&lt;MyTreeViewItem&gt; Children { get; set; }
          private Boolean _isSelected;
          public Boolean IsSelected
          {
              get { return _isSelected; }
              set { _isSelected = value; OnPropertyChanged("IsSelected"); }
          }
          private Boolean _isExpanded;
          public Boolean IsExpanded
          {
              get { return _isExpanded; }
              set { _isExpanded = value; OnPropertyChanged("IsExpanded"); }
          }
          private Boolean _isChecked;
          public Boolean IsChecked
          {
              get { return _isChecked; }
              set 
              { 
                  _isChecked = value; 
                  OnPropertyChanged("IsChecked");
                  if (Children != null)
                  {
                      ObservableCollection&lt;MyTreeViewItem&gt; children = Children;
                      foreach (MyTreeViewItem child in children)
                      {
                          child.IsChecked = value;
                      }
                  }
              }
          }
  
          public MyTreeViewItem()
          {
              IsSelected = false;
              IsExpanded = false;
              IsChecked = false;
              Name = "";
              Children = new ObservableCollection&lt;MyTreeViewItem&gt;();
          }
  
          public MyTreeViewItem(String name) : this()
          {
              Name = name;
          }
  
          public void AddChild(MyTreeViewItem item)
          {
              Children.Add(item);
          }
  
          public event PropertyChangedEventHandler PropertyChanged;
  
          public void OnPropertyChanged(String propertyName)
          {
              if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
          }
      }
  }
  </code></pre>
  
  <p>i am aware of the large memory usage and the large number of elements, however, i would expect that the performance to be roughly the same over the course of usage</p>
  
  <p>i read somewhere that there are potential memory leaks if the inotifypropertychanged is not used correctly, i tried to follow the offered advise, but it did not change this behaviour, besides there seams to be enough memory left</p>
  
  <p>so i am asking for any suggestions, on how to stabilize the performance</p>
  
  <p>my guess would be that the elements are loaded on demand when the parent elements are expanded, but not unloaded if they are contracted, but i do not have a sufficient knowledge of the background mechanics of a wpf treeview, so even an good insight into the latter would be very helpful</p>