Skip to content

Commit 07fcb9b

Browse files
committed
feat: Improve filtering API
1 parent 3dd346c commit 07fcb9b

File tree

4 files changed

+115
-13
lines changed

4 files changed

+115
-13
lines changed

SimpleDataGrid.Example/MainViewModel.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using SimpleDataGrid.Pagination;
2+
using System;
3+
using System.Collections.Generic;
24

35
namespace SimpleDataGrid.Example;
46

@@ -24,10 +26,26 @@ private static List<Person> GetPeople()
2426

2527
public void ApplyFilter(int minAge)
2628
{
27-
People.ClearFilters();
28-
People.AddFilter(p => p.Age >= minAge);
29+
People.SetFilter("minAge", p => p.Age >= minAge);
30+
}
31+
32+
public void ApplyMaxAgeFilter(int maxAge)
33+
{
34+
People.SetFilter("maxAge", p => p.Age <= maxAge);
2935
}
3036

37+
public void ApplyNameFilter(string namePrefix)
38+
{
39+
People.SetFilter("namePrefix", p => p.Name.StartsWith(namePrefix, StringComparison.OrdinalIgnoreCase));
40+
}
41+
42+
public void RemoveFilter(string key)
43+
{
44+
People.RemoveFilter(key);
45+
}
46+
47+
public IReadOnlyCollection<string> ActiveFilters => People.GetActiveFilters();
48+
3149
public void ClearFilter()
3250
{
3351
People.ClearFilters();

SimpleDataGrid.Example/MainWindow.xaml

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,36 @@
2222
<RowDefinition Height="Auto" />
2323
</Grid.RowDefinitions>
2424

25-
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5">
26-
<TextBox x:Name="SearchTextBox" Width="200" Margin="5" />
27-
<Button Content="Search" Click="SearchButton_Click" Margin="5" />
28-
<CheckBox x:Name="WildcardCheckBox" Content="Use Wildcards" VerticalAlignment="Center" Margin="5" />
29-
30-
<TextBox x:Name="MinAgeTextBox" Width="50" Margin="5" />
31-
<Button Content="Filter by Min Age" Click="FilterButton_Click" Margin="5" />
32-
<Button Content="Clear Filter" Click="ClearFilterButton_Click" Margin="5" />
25+
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="5">
26+
<StackPanel Orientation="Horizontal">
27+
<TextBox x:Name="SearchTextBox" Width="200" Margin="5" />
28+
<Button Content="Search" Click="SearchButton_Click" Margin="5" />
29+
<CheckBox x:Name="WildcardCheckBox" Content="Use Wildcards" VerticalAlignment="Center" Margin="5" />
30+
</StackPanel>
31+
<StackPanel Orientation="Horizontal">
32+
<TextBox x:Name="MinAgeTextBox" Width="50" Margin="5" />
33+
<Button Content="Filter by Min Age" Click="FilterButton_Click" Margin="5" />
34+
<TextBox x:Name="MaxAgeTextBox" Width="50" Margin="5" />
35+
<Button Content="Filter by Max Age" Click="MaxAgeFilterButton_Click" Margin="5" />
36+
<TextBox x:Name="NamePrefixTextBox" Width="100" Margin="5" />
37+
<Button Content="Filter by Name Prefix" Click="NamePrefixFilterButton_Click" Margin="5" />
38+
<Button Content="Clear Filters" Click="ClearFilterButton_Click" Margin="5" />
39+
</StackPanel>
40+
<ItemsControl ItemsSource="{Binding People.ActiveFilters}">
41+
<ItemsControl.ItemsPanel>
42+
<ItemsPanelTemplate>
43+
<StackPanel Orientation="Horizontal"/>
44+
</ItemsPanelTemplate>
45+
</ItemsControl.ItemsPanel>
46+
<ItemsControl.ItemTemplate>
47+
<DataTemplate>
48+
<StackPanel Orientation="Horizontal">
49+
<TextBlock Text="{Binding}" VerticalAlignment="Center" Margin="5,0"/>
50+
<Button Content="Remove" Click="RemoveFilterButton_Click" CommandParameter="{Binding}" Margin="5,0"/>
51+
</StackPanel>
52+
</DataTemplate>
53+
</ItemsControl.ItemTemplate>
54+
</ItemsControl>
3355
</StackPanel>
3456

3557
<controls:PagedDataGrid x:Name="PagedDataGrid" Grid.Row="1" PagedSource="{Binding People}" AutoGenerateColumns="True" />

SimpleDataGrid.Example/MainWindow.xaml.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using SimpleDataGrid.Controls;
22
using System.Windows;
3+
using System.Windows.Controls;
34

45
namespace SimpleDataGrid.Example;
56

@@ -60,4 +61,28 @@ private void GoToPageButton_Click(object sender, RoutedEventArgs e)
6061
viewModel.People.GoToPage(page);
6162
}
6263
}
64+
65+
private void MaxAgeFilterButton_Click(object sender, RoutedEventArgs e)
66+
{
67+
var viewModel = (MainViewModel)DataContext;
68+
if (int.TryParse(MaxAgeTextBox.Text, out var maxAge))
69+
{
70+
viewModel.ApplyMaxAgeFilter(maxAge);
71+
}
72+
}
73+
74+
private void NamePrefixFilterButton_Click(object sender, RoutedEventArgs e)
75+
{
76+
var viewModel = (MainViewModel)DataContext;
77+
viewModel.ApplyNameFilter(NamePrefixTextBox.Text);
78+
}
79+
80+
private void RemoveFilterButton_Click(object sender, RoutedEventArgs e)
81+
{
82+
var viewModel = (MainViewModel)DataContext;
83+
if (sender is Button button && button.CommandParameter is string key)
84+
{
85+
viewModel.RemoveFilter(key);
86+
}
87+
}
6388
}

SimpleDataGrid/Pagination/PagedCollection.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class PagedCollection<T> : IPagedCollection, INotifyPropertyChanged
1919
private IReadOnlyList<T> _source = [];
2020
private IReadOnlyList<T> _filtered = [];
2121

22-
private readonly List<Func<T, bool>> _filters = [];
22+
private readonly Dictionary<string, Func<T, bool>> _filters = [];
2323
private readonly List<(Func<T, object> selector, bool ascending)> _sorts = [];
2424
private Func<T, string>? _searchSelector;
2525
private string? _searchTerm;
@@ -35,6 +35,11 @@ public class PagedCollection<T> : IPagedCollection, INotifyPropertyChanged
3535
/// </summary>
3636
public event EventHandler? SortChanged;
3737

38+
/// <summary>
39+
/// Occurs when the filter changes.
40+
/// </summary>
41+
public event EventHandler? FilterChanged;
42+
3843
/// <summary>
3944
/// Initializes a new instance of the <see cref="PagedCollection{T}"/> class.
4045
/// </summary>
@@ -61,17 +66,49 @@ public void SetSource(IReadOnlyList<T> items)
6166
/// <param name="filter">The filter to add.</param>
6267
public void AddFilter(Func<T, bool> filter)
6368
{
64-
_filters.Add(filter);
69+
SetFilter(Guid.NewGuid().ToString(), filter);
70+
}
71+
72+
/// <summary>
73+
/// Adds or updates a filter in the collection.
74+
/// </summary>
75+
/// <param name="key">The key of the filter.</param>
76+
/// <param name="filter">The filter to add or update.</param>
77+
public void SetFilter(string key, Func<T, bool> filter)
78+
{
79+
_filters[key] = filter;
6580
ApplyFiltering();
81+
FilterChanged?.Invoke(this, EventArgs.Empty);
6682
}
6783

84+
/// <summary>
85+
/// Removes a filter from the collection.
86+
/// </summary>
87+
/// <param name="key">The key of the filter to remove.</param>
88+
public void RemoveFilter(string key)
89+
{
90+
if (_filters.Remove(key))
91+
{
92+
ApplyFiltering();
93+
FilterChanged?.Invoke(this, EventArgs.Empty);
94+
}
95+
}
96+
97+
/// <summary>
98+
/// Gets the keys of the active filters.
99+
/// </summary>
100+
/// <returns>A read-only collection of the active filter keys.</returns>
101+
public IReadOnlyCollection<string> GetActiveFilters() => _filters.Keys;
102+
103+
68104
/// <summary>
69105
/// Clears all filters from the collection.
70106
/// </summary>
71107
public void ClearFilters()
72108
{
73109
_filters.Clear();
74110
ApplyFiltering();
111+
FilterChanged?.Invoke(this, EventArgs.Empty);
75112
}
76113

77114
/// <summary>
@@ -116,7 +153,7 @@ private void ApplyFiltering()
116153
{
117154
IEnumerable<T> query = _source;
118155

119-
foreach (var filter in _filters)
156+
foreach (var filter in _filters.Values)
120157
{
121158
query = query.Where(filter);
122159
}

0 commit comments

Comments
 (0)