title: Apply a filter on a sorted ListCollectionView/ObservableCollection
body: <p><strong>What I have</strong></p>
  
  <p>I have a <code>UserControl</code> made of a <code>TextBox</code> and a <code>ListBox</code>. The <code>ListBox</code> has its <code>ItemsSource</code> bound to an <code>ObservableCollection</code> in a <code>DataContext</code> via a <code>ListCollectionView</code> with a custom sorting and filter as we'll see below. The purpose of the control is to display in the <code>ListBox</code> only the items (<code>string</code>s) in the source collection that contain the text in the <code>TextBox</code>. For that purpose I apply a filter on the <code>ListCollectionView</code>.</p>
  
  <p>I have two additional constraints. 1, my original collection is not alphabetically sorted but the items displayed in the <code>ListBox</code> are using a <code>ListCollectionView</code> <code>CustomSort</code>. 2, I must display only the first 5 items (alphabetically sorted) that match the string in the <code>TextBox</code>. I apply a filter on the <code>ListCollectionView</code> for that.</p>
  
  <p><strong>Expectation</strong></p>
  
  <p>Let's say my collection is defined as such in my <code>DataContext</code>:</p>
  
  <pre><code>this.AllItems = new ObservableCollection&lt;string&gt;
  {
      "Banana", 
      "Watermelon",
      "Peach",
      "Grape",
      "Apple",
      "Pineapple",
      "Cherry",
      "Durian",
      "Rambutan",
      "Strawberry",
      "Raspberry",
      "Lemon",
      "Orange",
      "Sugar cane",
      "Guava",
      "Tomato",
      "Coconut",
      "Melon",
      "Äpple",
      "Glaçon",
      "Etape",
      "Étape"
  };
  </code></pre>
  
  <p>And in my <code>TextBox</code> I input the letter 'e' (all comparisons done are case-insenstive). I expect the <code>ListBox</code> to display the following 5 items (<code>CurrentUICulture</code> is set to fr-FR):</p>
  
  <ul>
  <li>Apple</li>
  <li>Äpple</li>
  <li>Cherry</li>
  <li>Etape</li>
  <li>Étape</li>
  </ul>
  
  <p>because they are the first 5 items that contain the letter 'e' when sorted alphabetically. However I get the following items in my application:</p>
  
  <ul>
  <li>Apple</li>
  <li>Grape</li>
  <li>Peach</li>
  <li>Pineapple</li>
  <li>Watermelon</li>
  </ul>
  
  <p>because they are the first 5 items in my collection that contain the letter 'e' <strong>THEN</strong> sorted alphabetically.</p>
  
  <p><strong>My code</strong></p>
  
  <p>Here's the code to understand what I have and my problem.
  It should work virtually only using a copy/paste of the below (beware of namespaces and <code>CurrentUICulture</code>). I'm using C# 4.0.</p>
  
  <p>1) The <code>MainWindow</code></p>
  
  <pre><code>&lt;Window x:Class="MyNamespace.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"
          xmlns:local="clr-namespace:MyNamespace"&gt;
      &lt;Window.Resources&gt;
          &lt;local:FoobarViewModel x:Key="Foobar"/&gt;
      &lt;/Window.Resources&gt;
      &lt;StackPanel&gt;
          &lt;local:Foobar DataContext="{StaticResource Foobar}" AllItems="{Binding AllItems}"/&gt;
      &lt;/StackPanel&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>2) The class used as the <code>DataContext</code></p>
  
  <pre><code>public class FoobarViewModel : INotifyPropertyChanged
  {
      private ObservableCollection&lt;string&gt; allItems;
      public event PropertyChangedEventHandler PropertyChanged;
  
      public FoobarViewModel()
      {
          this.AllItems = new ObservableCollection&lt;string&gt;
          {
              "Banana", 
              "Watermelon",
              "Peach",
              "Grape",
              "Apple",
              "Pineapple",
              "Cherry",
              "Durian",
              "Rambutan",
              "Strawberry",
              "Raspberry",
              "Lemon",
              "Orange",
              "Sugar cane",
              "Guava",
              "Tomato",
              "Coconut",
              "Melon",
              "Äpple",
              "Glaçon",
              "Etape",
              "Étape"
          };
      }
  
      public ObservableCollection&lt;string&gt; AllItems
      {
          get
          {
              return this.allItems;
          }
          set
          {
              this.allItems = value;
              this.OnPropertyChanged("AllItems");
          }
      }
  
      private void OnPropertyChanged(string propertyName)
      {
          var handler = this.PropertyChanged;
          if (handler != null)
          {
              handler(this, new PropertyChangedEventArgs(propertyName));
          }
      }
  }
  </code></pre>
  
  <p>3) The XAML of my <code>UserControl</code></p>
  
  <pre><code>&lt;UserControl x:Class="MyNamespace.Foobar"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
               xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
               mc:Ignorable="d" 
               d:DesignHeight="300" d:DesignWidth="300"&gt;
      &lt;Grid&gt;
          &lt;Grid.RowDefinitions&gt;
              &lt;RowDefinition/&gt;
              &lt;RowDefinition/&gt;
          &lt;/Grid.RowDefinitions&gt;
  
          &lt;TextBox x:Name="textbox" Grid.Row="0"/&gt;
          &lt;ListBox x:Name="listbox" Grid.Row="1"/&gt;
      &lt;/Grid&gt;
  &lt;/UserControl&gt;
  </code></pre>
  
  <p>4) And finally, most important the code behind of my <code>UserControl</code> <code>Foobar</code>.</p>
  
  <pre><code>public partial class Foobar : UserControl
  {
      #region Fields
      public static readonly DependencyProperty AllItemsProperty = DependencyProperty.Register(
          "AllItems",
          typeof(IEnumerable&lt;string&gt;),
          typeof(Foobar),
          new PropertyMetadata(AllItemsChangedCallback));
  
      private const int MaxItems = 5;
      #endregion
  
      #region Constructors
      public Foobar()
      {
          InitializeComponent();
  
          textbox.KeyUp += TextboxKeyUp;
      }
      #endregion
  
      #region Properties
      public IEnumerable&lt;string&gt; AllItems
      {
          get { return (IEnumerable&lt;string&gt;)this.GetValue(AllItemsProperty); }
          set { this.SetValue(AllItemsProperty, value); }
      }
      #endregion
  
      #region Methods
      private void TextboxKeyUp(object sender, KeyEventArgs e)
      {
          TextBox localTextBox = sender as TextBox;
          if (localTextBox != null)
          {
              var items = ((ListCollectionView)listbox.ItemsSource).SourceCollection;
  
              if (items.Cast&lt;string&gt;().Any(x =&gt; x.ToLower(CultureInfo.CurrentUICulture).Contains(localTextBox.Text.ToLower(CultureInfo.CurrentUICulture))))
              {
                  this.ApplyFilter();
                  listbox.Visibility = Visibility.Visible;
              }
              else
              {
                  listbox.Visibility = Visibility.Collapsed;
              }
          }
      }
  
      private static void AllItemsChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
      {
          Foobar control = sender as Foobar;
          if (control != null)
          {
              List&lt;string&gt; source = new List&lt;string&gt;((IEnumerable&lt;string&gt;)e.NewValue);
  
              ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(source);
              view.CustomSort = new CustomSort();
              control.listbox.ItemsSource = view;
              control.ApplyFilter();
          }
      }
  
      private void ApplyFilter()
      {
          ListCollectionView view = (ListCollectionView)listbox.ItemsSource;
  
          int index = 0;
          view.Filter = x =&gt;
          {
              bool result = x.ToString().ToLower(CultureInfo.CurrentUICulture).Contains(textbox.Text.ToLower(CultureInfo.CurrentUICulture));
              if (result)
              {
                  index++;
              }
  
              return index &lt;= MaxItems &amp;&amp; result;
          };
      }
      #endregion
  
      private class CustomSort : IComparer
      {
          public int Compare(object x, object y)
          {
              return String.Compare(x.ToString(), y.ToString(), CultureInfo.CurrentUICulture, CompareOptions.IgnoreCase);
          }
      }
  }
  </code></pre>
  
  <p>The whole code is working as expected, except the filtering which is done in the <code>ApplyFilter</code> method. Basically, this method just checks each and every item in the collection against whatever is in the <code>TextBox</code> and provided there is not already more than the maximum number of items returned, the item will be included in the filter. When I debug this method, I can see that items are browsed in the original order of the collection and not in the sorted order althought the filter seem to be done on the <code>ListCollectionView</code> and not the <code>ObservableCollection&lt;string&gt;</code>.</p>
  
  <p>It seems the filter is applied first, then the sorting. I want the sorting to apply first then the filtering.</p>
  
  <p><strong>My question</strong></p>
  
  <p>How can I apply the filter on the sorted <code>ListCollectionView</code> and not on the original non-sorted collection?</p>