Thursday, 11 December 2008

List Filtering in WPF with M-V-VM

The first Windows Forms application I ever wrote was an anagram generator back in 2002. As part of my ongoing efforts to learn WPF and M-V-VM, I have been porting it to WPF, and adding a few new features along the way. Today, I wanted to add a TextBox that would allow you filter the anagram results to only show results that contained a specific sub-string.

The first task is to create a TextBox and a ListBox in XAML and set their binding properties. We want the filter to update every time a user types a character in, so we use the UpdateSourceTrigger to specify this.

<TextBox Margin="5" 
     Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}" 
     Width="150" />
...
<ListBox Margin="5" ItemsSource="{Binding Phrases}" />

>Now we need to create the corresponding Filter and Phrases properties in our ViewModel. Then we need to get an ICollectionView based on our ObservableCollection of phrases. Once we have done this, we can attach a delegate to it that will perform our filtering. The final step is to call Refresh on the view whenever the user changes the filter box.

private ICollectionView phrasesView;
private string filter;

public ObservableCollection<string> Phrases { get; private set; }
                    
public AnagramViewModel()
{
   ...
   Phrases = new ObservableCollection<string>();
   phrasesView = CollectionViewSource.GetDefaultView(Phrases);
   phrasesView.Filter = o => String.IsNullOrEmpty(Filter) ? true : ((string)o).Contains(Filter); 
}

public string Filter 
{
   get
   {
      return filter;
   }
   set
   {
      if (value != filter)
      {
         filter = value;
         phrasesView.Refresh();
         RaisePropertyChanged("Filter");
      }
   }
}

And that's all there is to it. It can be kept nicely encapsulated within the ViewModel without the need for any code-behind in the view.

List filtering in WPF

Post a Comment