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: wpf,livesearch,dynamic filtering
1 comment Sunday 25th November, 2007