Skip to content

Commit da792dd

Browse files
committed
feat: Add sorting support
1 parent b8132ad commit da792dd

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

SimpleDataGrid/Controls/PageDataGrid.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ public IPagedCollection? PagedSource
2525
set => SetValue(PagedSourceProperty, value);
2626
}
2727

28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="PagedDataGrid"/> class.
30+
/// </summary>
31+
public PagedDataGrid()
32+
{
33+
Sorting += OnSorting;
34+
}
35+
36+
2837
private static void OnPagedSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
2938
{
3039
if (d is PagedDataGrid grid && e.NewValue is IPagedCollection paged)
@@ -39,6 +48,13 @@ private static void OnPagedSourceChanged(DependencyObject d, DependencyPropertyC
3948
};
4049
}
4150
}
51+
52+
/// <summary>
53+
/// Handles the <see cref="DataGrid.Sorting"/> event.
54+
/// </summary>
55+
/// <param name="sender">The sender of the event.</param>
56+
/// <param name="e">The event data.</param>
57+
protected virtual void OnSorting(object sender, DataGridSortingEventArgs e) { }
4258
}
4359

4460
/// <summary>
@@ -55,4 +71,32 @@ public class PagedDataGrid<T> : PagedDataGrid
5571
get => (PagedCollection<T>?)base.PagedSource;
5672
set => base.PagedSource = value;
5773
}
74+
75+
/// <summary>
76+
/// Handles the <see cref="DataGrid.Sorting"/> event.
77+
/// </summary>
78+
/// <param name="sender">The sender of the event.</param>
79+
/// <param name="e">The event data.</param>
80+
protected override void OnSorting(object sender, DataGridSortingEventArgs e)
81+
{
82+
if (PagedSource == null) return;
83+
84+
var direction = e.Column.SortDirection == System.ComponentModel.ListSortDirection.Ascending
85+
? System.ComponentModel.ListSortDirection.Descending
86+
: System.ComponentModel.ListSortDirection.Ascending;
87+
88+
e.Column.SortDirection = direction;
89+
90+
var propertyName = e.Column.SortMemberPath;
91+
if (string.IsNullOrEmpty(propertyName)) return;
92+
93+
var parameter = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
94+
var property = System.Linq.Expressions.Expression.Property(parameter, propertyName);
95+
var lambda = System.Linq.Expressions.Expression.Lambda<Func<T, object>>(System.Linq.Expressions.Expression.Convert(property, typeof(object)), parameter);
96+
97+
PagedSource.SetSort(lambda.Compile(), direction == System.ComponentModel.ListSortDirection.Ascending);
98+
99+
e.Handled = true;
100+
}
101+
58102
}

SimpleDataGrid/Pagination/PagedCollection.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,21 @@ public class PagedCollection<T> : IPagedCollection, INotifyPropertyChanged
1616
private IReadOnlyList<T> _filtered = [];
1717

1818
private readonly List<Func<T, bool>> _filters = [];
19+
private readonly List<(Func<T, object> selector, bool ascending)> _sorts = [];
1920
private Func<T, string>? _searchSelector;
2021
private string? _searchTerm;
2122
private bool _useWildcards;
2223

24+
/// <summary>
25+
/// Gets a value indicating whether the collection is sorted.
26+
/// </summary>
27+
public bool IsSorted => _sorts.Count > 0;
28+
29+
/// <summary>
30+
/// Occurs when the sorting changes.
31+
/// </summary>
32+
public event EventHandler? SortChanged;
33+
2334
/// <summary>
2435
/// Initializes a new instance of the <see cref="PagedCollection{T}"/> class.
2536
/// </summary>
@@ -73,6 +84,30 @@ public void SetSearch(Func<T, string> selector, string? term, bool useWildcards
7384
ApplyFiltering();
7485
}
7586

87+
/// <summary>
88+
/// Sets the sort criteria for the collection.
89+
/// </summary>
90+
/// <typeparam name="TKey">The type of the key to sort by.</typeparam>
91+
/// <param name="selector">A function to extract the key for sorting.</param>
92+
/// <param name="ascending">A value indicating whether to sort in ascending order.</param>
93+
public void SetSort<TKey>(Func<T, TKey> selector, bool ascending)
94+
{
95+
_sorts.Clear();
96+
_sorts.Add((x => selector(x)!, ascending));
97+
ApplyFiltering();
98+
SortChanged?.Invoke(this, EventArgs.Empty);
99+
}
100+
101+
/// <summary>
102+
/// Clears the sort criteria from the collection.
103+
/// </summary>
104+
public void ClearSort()
105+
{
106+
_sorts.Clear();
107+
ApplyFiltering();
108+
SortChanged?.Invoke(this, EventArgs.Empty);
109+
}
110+
76111
private void ApplyFiltering()
77112
{
78113
IEnumerable<T> query = _source;
@@ -97,6 +132,23 @@ private void ApplyFiltering()
97132
}
98133
}
99134

135+
if (_sorts.Count > 0)
136+
{
137+
IOrderedEnumerable<T>? orderedQuery = null;
138+
foreach (var (selector, ascending) in _sorts)
139+
{
140+
if (orderedQuery == null)
141+
{
142+
orderedQuery = ascending ? query.OrderBy(selector) : query.OrderByDescending(selector);
143+
}
144+
else
145+
{
146+
orderedQuery = ascending ? orderedQuery.ThenBy(selector) : orderedQuery.ThenByDescending(selector);
147+
}
148+
}
149+
query = orderedQuery ?? query;
150+
}
151+
100152
_filtered = [.. query];
101153
_currentPage = 0;
102154
RaiseAllChanged();

0 commit comments

Comments
 (0)