Posts Tagged dynamic filtering

WPF: Dynamic Filtering Data – the simple approach

You often find yourself wanting to quickly filter data based on a criteria defined by a user in an application.  A classic example is filtering what’s shown in a listbox by what a user has typed into a textbox.

There are many approaches to solving the problem but a quick and simple approach is: (first the xaml):

<Window x:Class="Window1" 
  xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 
  xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 
  xmlns:local="clr-namespace:contactManager" 
  xmlns:system="clr-namespace:System;assembly=mscorlib"
  Title="Window1" Height="598" Width="1015">
  <Window.Resources>
     <local:contacts x:Key="myContacts" />    
     <CollectionViewSource x:Key="contactsViewSource"
         Source="{StaticResource myContacts}" Filter="CollectionViewSource_Filter" />

  </Window.Resources>
  <Grid Name="Grid1">
    <Grid.RowDefinitions>
      <RowDefinition Height="60*" />
      <RowDefinition Height="423*" />
    </Grid.RowDefinitions>
    <TextBox Margin="62,26,16,0" Name="txtSearch" Height="23" VerticalAlignment="Top"
     AcceptsReturn="True" FontStyle="Italic" KeyUp="txtSearch_KeyUp" />
    <Label Margin="12,12,66,0" Name="Label1" Height="28" VerticalAlignment="Top">Search</Label>

    <ListBox Grid.Row="1" Name="lstContacts" IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding Source={StaticResource contactsViewSource}}" />
  </Grid>

</Window>

The local resource contacts is a class that is defined in the application.  The namespace is imported into the XAML with xmlns:local=”clr-namespace:contactManager“‘.  The class itself is referenced in XAML by <local:contacts x:Key=”myContacts” />‘.

The class itself inherits from an observableCollection – although the approach would work with any datasource that can be bound to the listbox. After contacts has been imported – we setup a collectionViewSource – rather than using the default viewSource provided by WPF.

The code behind to connect the filter text with the filter applied to the listbox is:

Partial Public Class Window1
  Private Function findString(ByVal haystack As String, ByVal needle As String, _
                                 Optional ByVal comparison As StringComparison _
                                    = StringComparison.CurrentCultureIgnoreCase) As Integer
    ' We are using string.indexOf rather than string.contains as string.contains
    ' doesn't allow us to specify CurrentCultureIgnoreCase
    Return haystack.IndexOf(needle, 0, comparison) 

  End Function 

Private Sub CollectionViewSource_Filter(ByVal sender As System.Object, _
                                    ByVal e As System.Windows.Data.FilterEventArgs)
   ' Cast the listbox item to the type used
  Dim thisContact As contact = CType(e.Item, contact) 

  If (thisContact IsNot Nothing) Then  ' Handle an empty item 

    If String.IsNullOrEmpty(txtSearch.Text) Then
      ' Make sure we have some text that we wish to filter

      e.Accepted = True
      ' If we don't then we want all items to appear in the listbox

    Else
      ' findString returns the index of the needle (search text) in
      ' the haystack (text to be searched)
      ' IndexOf returns -1 if the needle isn't found in the haystack 

      If (findString(thisContact.firstName, txtSearch.Text) > -1) _
               Or (findString(thisContact.lastName, txtSearch.Text) > -1) Then 

        ' The needle exists in the haystack - so accept this entry
        e.Accepted = True 

      Else
        ' This item doesn't contain the needle we are looking for

        e.Accepted = False

      End If 

    End If

  Else
    ' thisContact IS nothing - so don't bother displaying it 

    e.Accepted = False 

  End If 

End Sub 

Private Sub txtSearch_KeyUp(ByVal sender As System.Object, _
                                ByVal e As System.Windows.Input.KeyEventArgs)
' This event will be raised whenever the keyUp event occurs on the
' textbox that we are using to filter
' Do a simple refresh on the listbox 

    CType(Me.FindResource("contactsViewSource"), CollectionViewSource).View.Refresh() 

  End Sub 

End Class 

  And that's it - a listbox containing items is filtered based on the text typed by the user in a search box.

Technorati Tags: ,,

1 comment Sunday 25th November, 2007


Recent Posts

a

Tags

AI CF chef cognative processes cognition components DataBinding deployment Development development tips dev tips distributed php distrubuted dynamic filtering evolution filtering data flashdrive frameworks genetics google hosting Katmai NLP ObservableCollection PHP problems with readyboost provisioning ReadyBoost Research SD serverside JS sitemap site stats social evolution SQL 2005 SQL 2008 SQL Server Symfony testing virtual machine Vista Visual Studio 2008 vm WPF xD

The Cloud...

.NET AI Blogroll Compatible Applications Development evolution genetics Internet Microsoft Mobiles MUD's NLP & MT observations Origami other fluff PHP Poetry Research Smarty Symfony tips Vista Visual Studio WCF/Indigo Wireless Technology WordPress world WPF WWF x64

Blogroll

Feeds & Links

Games

NLP & MT

Symfony

VoIP

Meta