Search code examples
c#wpfsearchvisual-studio-2017wpfdatagrid

How to filter records in a DataGrid?


I am trying to filter my data for the selected column based on a search box. I have this so far, based on this post: filter wpf datagrid values from a textbox

DataGridCollection:

public ICollectionView DataGridCollection
{
   get { return _dataGridCollection; }
   set { _dataGridCollection = value; NotifyPropertyChanged("DataGridCollection"); }
}

Filter collection:

private void FilterCollection()
{
    if (_dataGridCollection != null)
    {
        _dataGridCollection.Refresh();
    }
}

Data source:

DataTable pixsellOrders = SqlConnect(query);    
Grid.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate { DataGridCollection = CollectionViewSource.GetDefaultView(pixsellOrders); });
DataGridCollection.Filter = new Predicate<object>(filter);

Filter button (right-click):

private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        string filter = "";
        FilterBox.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate { filter = FilterBox.Text; });

        if (filter == "")
        {
            Console.WriteLine("no filter");
            return;
        }
        else
        {
            Console.WriteLine(filter);
            FilterCollection();
        }
    }

Based on example:

private bool filter(object item)
    {
        if (item.Subject.Contains(_searchstr) || item.Reference.Contains(searchstr))
        {
            return true;
        }
        return false;
    }

XAML:

<Grid DataContext="{Binding ElementName=ResultsWindow}">
    <DataGrid x:Name="Grid" HorizontalAlignment="Stretch" Height="Auto" Margin="20,45,20,60" VerticalAlignment="Stretch" Width="Auto" ItemsSource="{Binding DataGridCollection}"  >
        <DataGrid.Resources>
            <ContextMenu x:Key="DataGridColumnHeaderContextMenu">
                <MenuItem Header="Filter" Click="MenuItem_Click"/>
            </ContextMenu>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContextMenu"
                Value="{StaticResource DataGridColumnHeaderContextMenu}"/>
            </Style>
        </DataGrid.Resources>
    </DataGrid>
    <Button x:Name="BtnBack" Content="Back" HorizontalAlignment="Right" Margin="0,0,20,20" VerticalAlignment="Bottom" Width="76" Click="BtnBack_Click"/>
    <TextBox Height="27" Margin="65,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="524" Name="FilterBox"/>
    <Label Content="Filter" HorizontalAlignment="Left" Margin="20,10,0,0" VerticalAlignment="Top"/>
</Grid>

In the example the columns are being declared explicitly in the filter (private bool filter). I would like to filter only on the column that is selected (right click the column header and choose filter from the context menu). How do I tweak what I have to do this? Unfortunately I don't have much experience with XAML.


Solution

  • The way to filter a DataTable is to set the RowFilter property of the DataView: https://msdn.microsoft.com/en-us/library/system.data.dataview.rowfilter(v=vs.110).aspx. There are some examples available here: http://www.csharp-examples.net/dataview-rowfilter/.

    You cannot filter a DataView of a DataTable using the Filter property of the ICollectionView. This is not supported:

    Why errors when filters DataTable with CollectionView?