Skip to content

Commit 3dd346c

Browse files
committed
feat: Add page navigation enhancements
1 parent da792dd commit 3dd346c

File tree

4 files changed

+118
-6
lines changed

4 files changed

+118
-6
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows.Data;
4+
5+
namespace SimpleDataGrid.Example.Converters
6+
{
7+
public class ItemCountConverter : IMultiValueConverter
8+
{
9+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
10+
{
11+
if (values.Length == 4 && values[0] is int count && values[1] is int page && values[2] is int total && values[3] is int pageSize)
12+
{
13+
var start = (page - 1) * pageSize + 1;
14+
var end = start + count - 1;
15+
return $"Showing items {start}-{end} of {total}";
16+
}
17+
return string.Empty;
18+
}
19+
20+
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
21+
{
22+
throw new NotImplementedException();
23+
}
24+
}
25+
}

SimpleDataGrid.Example/MainWindow.xaml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@
66
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
77
xmlns:local="clr-namespace:SimpleDataGrid.Example"
88
xmlns:controls="clr-namespace:SimpleDataGrid.Controls;assembly=SimpleDataGrid"
9+
xmlns:converters="clr-namespace:SimpleDataGrid.Example.Converters"
910
mc:Ignorable="d"
1011
Title="MainWindow" Height="450" Width="800">
12+
<Window.Resources>
13+
<converters:ItemCountConverter x:Key="ItemCountConverter"/>
14+
</Window.Resources>
1115
<Window.DataContext>
1216
<local:MainViewModel />
1317
</Window.DataContext>
@@ -31,11 +35,31 @@
3135
<controls:PagedDataGrid x:Name="PagedDataGrid" Grid.Row="1" PagedSource="{Binding People}" AutoGenerateColumns="True" />
3236

3337
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
34-
<Button Content="Previous" Click="PreviousButton_Click" Margin="5" />
35-
<TextBlock Text="{Binding People.CurrentPage}" VerticalAlignment="Center" Margin="5" />
36-
<TextBlock Text="/" VerticalAlignment="Center" />
37-
<TextBlock Text="{Binding People.TotalPages}" VerticalAlignment="Center" Margin="5" />
38-
<Button Content="Next" Click="NextButton_Click" Margin="5" />
38+
<Button Content="First" Click="FirstButton_Click" Margin="5" IsEnabled="{Binding People.HasPrevious}"/>
39+
<Button Content="Previous" Click="PreviousButton_Click" Margin="5" IsEnabled="{Binding People.HasPrevious}"/>
40+
<TextBlock VerticalAlignment="Center" Margin="5">
41+
<TextBlock.Text>
42+
<MultiBinding StringFormat="Page {0} of {1}">
43+
<Binding Path="People.CurrentPage"/>
44+
<Binding Path="People.TotalPages"/>
45+
</MultiBinding>
46+
</TextBlock.Text>
47+
</TextBlock>
48+
<Button Content="Next" Click="NextButton_Click" Margin="5" IsEnabled="{Binding People.HasNext}"/>
49+
<Button Content="Last" Click="LastButton_Click" Margin="5" IsEnabled="{Binding People.HasNext}"/>
50+
<TextBlock Text="Go to page:" VerticalAlignment="Center" Margin="5,0,0,0"/>
51+
<TextBox x:Name="PageTextBox" Width="30" Margin="5,0,0,0"/>
52+
<Button Content="Go" Click="GoToPageButton_Click" Margin="5,0,0,0"/>
53+
<TextBlock VerticalAlignment="Center" Margin="10,0,0,0">
54+
<TextBlock.Text>
55+
<MultiBinding Converter="{StaticResource ItemCountConverter}">
56+
<Binding Path="People.CurrentPageItems.Count"/>
57+
<Binding Path="People.CurrentPage"/>
58+
<Binding Path="People.TotalItems"/>
59+
<Binding Path="People.PageSize"/>
60+
</MultiBinding>
61+
</TextBlock.Text>
62+
</TextBlock>
3963
</StackPanel>
4064
</Grid>
4165
</Window>

SimpleDataGrid.Example/MainWindow.xaml.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,25 @@ private void ClearFilterButton_Click(object sender, RoutedEventArgs e)
3939
var viewModel = (MainViewModel)DataContext;
4040
viewModel.ClearFilter();
4141
}
42+
43+
private void FirstButton_Click(object sender, RoutedEventArgs e)
44+
{
45+
var viewModel = (MainViewModel)DataContext;
46+
viewModel.People.GoToFirstPage();
47+
}
48+
49+
private void LastButton_Click(object sender, RoutedEventArgs e)
50+
{
51+
var viewModel = (MainViewModel)DataContext;
52+
viewModel.People.GoToLastPage();
53+
}
54+
55+
private void GoToPageButton_Click(object sender, RoutedEventArgs e)
56+
{
57+
var viewModel = (MainViewModel)DataContext;
58+
if (int.TryParse(PageTextBox.Text, out var page))
59+
{
60+
viewModel.People.GoToPage(page);
61+
}
62+
}
4263
}

SimpleDataGrid/Pagination/PagedCollection.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ public class PagedCollection<T> : IPagedCollection, INotifyPropertyChanged
1212
{
1313
private readonly int _pageSize;
1414
private int _currentPage;
15+
/// <summary>
16+
/// Gets the number of items to display per page.
17+
/// </summary>
18+
public int PageSize => _pageSize;
1519
private IReadOnlyList<T> _source = [];
1620
private IReadOnlyList<T> _filtered = [];
1721

@@ -174,7 +178,12 @@ private static string WildcardToRegex(string pattern)
174178
/// <summary>
175179
/// Gets the total number of pages.
176180
/// </summary>
177-
public int TotalPages => (int)Math.Ceiling((double)_filtered.Count / _pageSize);
181+
public int TotalPages => Math.Max(1, (int)Math.Ceiling((double)_filtered.Count / _pageSize));
182+
183+
/// <summary>
184+
/// Gets the total number of items in the filtered collection.
185+
/// </summary>
186+
public int TotalItems => _filtered.Count;
178187

179188
/// <summary>
180189
/// Gets a value indicating whether there is a next page.
@@ -216,6 +225,39 @@ public void PreviousPage()
216225
}
217226
}
218227

228+
/// <summary>
229+
/// Moves to a specific page.
230+
/// </summary>
231+
/// <param name="page">The page to move to.</param>
232+
public void GoToPage(int page)
233+
{
234+
var newPage = Math.Clamp(page - 1, 0, TotalPages - 1);
235+
if (newPage != _currentPage)
236+
{
237+
_currentPage = newPage;
238+
OnPropertyChanged(nameof(CurrentPageItems));
239+
OnPropertyChanged(nameof(CurrentPage));
240+
OnPropertyChanged(nameof(HasNext));
241+
OnPropertyChanged(nameof(HasPrevious));
242+
}
243+
}
244+
245+
/// <summary>
246+
/// Moves to the first page.
247+
/// </summary>
248+
public void GoToFirstPage()
249+
{
250+
GoToPage(1);
251+
}
252+
253+
/// <summary>
254+
/// Moves to the last page.
255+
/// </summary>
256+
public void GoToLastPage()
257+
{
258+
GoToPage(TotalPages);
259+
}
260+
219261
private void RaiseAllChanged()
220262
{
221263
OnPropertyChanged(nameof(CurrentPageItems));

0 commit comments

Comments
 (0)