Merge pull request #182 from Soar360/main

为 Pagination 控件增加 CurrentPageChanged 事件
This commit is contained in:
Dong Bin
2024-03-25 09:49:34 +08:00
committed by GitHub
3 changed files with 86 additions and 20 deletions

View File

@@ -24,6 +24,8 @@
PageSizeOptions="10, 20, 50, 100" PageSizeOptions="10, 20, 50, 100"
ShowQuickJump="{Binding #quickJumperSelector.IsChecked}" ShowQuickJump="{Binding #quickJumperSelector.IsChecked}"
ShowPageSizeSelector="{Binding #pageSizeSelector.IsChecked}" ShowPageSizeSelector="{Binding #pageSizeSelector.IsChecked}"
Command="{Binding LoadPageCommand}"
CommandParameter="{Binding $self.CurrentPage}"
TotalCount="600" /> TotalCount="600" />
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -1,11 +1,25 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
using Avalonia.Collections; using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace Ursa.Demo.ViewModels; namespace Ursa.Demo.ViewModels;
public class PaginationDemoViewModel: ViewModelBase public class PaginationDemoViewModel : ViewModelBase
{ {
public AvaloniaList<int> PageSizes { get; set; } = new() { 10, 20, 50, 100 }; public AvaloniaList<int> PageSizes { get; set; } = new() { 10, 20, 50, 100 };
public ICommand LoadPageCommand { get; }
public PaginationDemoViewModel()
{
this.LoadPageCommand = new RelayCommand<int?>(LoadPage);
}
private void LoadPage(int? pageIndex)
{
Debug.WriteLine($"Loading page {pageIndex}");
}
} }

View File

@@ -7,6 +7,7 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Styling; using Avalonia.Styling;
using Irihi.Avalonia.Shared.Helpers; using Irihi.Avalonia.Shared.Helpers;
using System.Windows.Input;
namespace Ursa.Controls; namespace Ursa.Controls;
@@ -30,16 +31,53 @@ public class Pagination: TemplatedControl
private StackPanel? _buttonPanel; private StackPanel? _buttonPanel;
private readonly PaginationButton[] _buttons = new PaginationButton[7]; private readonly PaginationButton[] _buttons = new PaginationButton[7];
private NumericIntUpDown? _quickJumpInput; private NumericIntUpDown? _quickJumpInput;
public static readonly StyledProperty<int?> CurrentPageProperty = AvaloniaProperty.Register<Pagination, int?>( public static readonly StyledProperty<int?> CurrentPageProperty = AvaloniaProperty.Register<Pagination, int?>(
nameof(CurrentPage)); nameof(CurrentPage));
public int? CurrentPage public int? CurrentPage
{ {
get => GetValue(CurrentPageProperty); get => GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value); set => SetValue(CurrentPageProperty, value);
} }
private void OnCurrentPageChanged(AvaloniaPropertyChangedEventArgs<int?> args)
{
int? oldValue = args.GetOldValue<int?>();
int? newValue = args.GetNewValue<int?>();
var e = new ValueChangedEventArgs<int>(CurrentPageChangedEvent, oldValue, newValue);
RaiseEvent(e);
}
public static readonly RoutedEvent<ValueChangedEventArgs<int>> CurrentPageChangedEvent =
RoutedEvent.Register<Pagination, ValueChangedEventArgs<int>>(nameof(CurrentPageChanged), RoutingStrategies.Bubble);
/// <summary>
/// Raised when the <see cref="CurrentPage"/> changes.
/// </summary>
public event EventHandler<ValueChangedEventArgs<int>>? CurrentPageChanged
{
add => AddHandler(CurrentPageChangedEvent, value);
remove => RemoveHandler(CurrentPageChangedEvent, value);
}
public static readonly StyledProperty<ICommand?> CommandProperty = AvaloniaProperty.Register<Pagination, ICommand?>(
nameof(Command));
public ICommand? Command
{
get => GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public static readonly StyledProperty<object?> CommandParameterProperty = AvaloniaProperty.Register<Pagination, object?>(nameof(CommandParameter));
public object? CommandParameter
{
get => this.GetValue(CommandParameterProperty);
set => this.SetValue(CommandParameterProperty, value);
}
public static readonly StyledProperty<int> TotalCountProperty = AvaloniaProperty.Register<Pagination, int>( public static readonly StyledProperty<int> TotalCountProperty = AvaloniaProperty.Register<Pagination, int>(
nameof(TotalCount)); nameof(TotalCount));
@@ -54,7 +92,7 @@ public class Pagination: TemplatedControl
public static readonly StyledProperty<int> PageSizeProperty = AvaloniaProperty.Register<Pagination, int>( public static readonly StyledProperty<int> PageSizeProperty = AvaloniaProperty.Register<Pagination, int>(
nameof(PageSize), defaultValue: 10); nameof(PageSize), defaultValue: 10);
/// <summary> /// <summary>
/// Page size. /// Page size.
/// </summary> /// </summary>
@@ -107,7 +145,7 @@ public class Pagination: TemplatedControl
public static readonly StyledProperty<bool> ShowQuickJumpProperty = AvaloniaProperty.Register<Pagination, bool>( public static readonly StyledProperty<bool> ShowQuickJumpProperty = AvaloniaProperty.Register<Pagination, bool>(
nameof(ShowQuickJump)); nameof(ShowQuickJump));
public bool ShowQuickJump public bool ShowQuickJump
{ {
get => GetValue(ShowQuickJumpProperty); get => GetValue(ShowQuickJumpProperty);
@@ -116,9 +154,11 @@ public class Pagination: TemplatedControl
static Pagination() static Pagination()
{ {
PageSizeProperty.Changed.AddClassHandler<Pagination, int>((pagination, args)=>pagination.OnPageSizeChanged(args)); PageSizeProperty.Changed.AddClassHandler<Pagination, int>((pagination, args) => pagination.OnPageSizeChanged(args));
CurrentPageProperty.Changed.AddClassHandler<Pagination, int?>((pagination, args) => CurrentPageProperty.Changed.AddClassHandler<Pagination, int?>((pagination, args) =>
pagination.UpdateButtonsByCurrentPage(args.NewValue.Value)); pagination.UpdateButtonsByCurrentPage(args.NewValue.Value));
CurrentPageProperty.Changed.AddClassHandler<Pagination, int?>((pagination, args) =>
pagination.OnCurrentPageChanged(args));
TotalCountProperty.Changed.AddClassHandler<Pagination, int>((pagination, args) => TotalCountProperty.Changed.AddClassHandler<Pagination, int>((pagination, args) =>
pagination.UpdateButtonsByCurrentPage(pagination.CurrentPage)); pagination.UpdateButtonsByCurrentPage(pagination.CurrentPage));
} }
@@ -142,19 +182,19 @@ public class Pagination: TemplatedControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton); Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton);
_previousButton = e.NameScope.Find<PaginationButton>(PART_PreviousButton); _previousButton = e.NameScope.Find<PaginationButton>(PART_PreviousButton);
_nextButton = e.NameScope.Find<PaginationButton>(PART_NextButton); _nextButton = e.NameScope.Find<PaginationButton>(PART_NextButton);
_buttonPanel = e.NameScope.Find<StackPanel>(PART_ButtonPanel); _buttonPanel = e.NameScope.Find<StackPanel>(PART_ButtonPanel);
Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton); Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton);
KeyDownEvent.RemoveHandler(OnQuickJumpInputKeyDown, _quickJumpInput); KeyDownEvent.RemoveHandler(OnQuickJumpInputKeyDown, _quickJumpInput);
LostFocusEvent.RemoveHandler(OnQuickJumpInputLostFocus, _quickJumpInput); LostFocusEvent.RemoveHandler(OnQuickJumpInputLostFocus, _quickJumpInput);
_quickJumpInput = e.NameScope.Find<NumericIntUpDown>(PART_QuickJumpInput); _quickJumpInput = e.NameScope.Find<NumericIntUpDown>(PART_QuickJumpInput);
KeyDownEvent.AddHandler(OnQuickJumpInputKeyDown, _quickJumpInput); KeyDownEvent.AddHandler(OnQuickJumpInputKeyDown, _quickJumpInput);
LostFocusEvent.AddHandler(OnQuickJumpInputLostFocus, _quickJumpInput); LostFocusEvent.AddHandler(OnQuickJumpInputLostFocus, _quickJumpInput);
InitializePanelButtons(); InitializePanelButtons();
UpdateButtonsByCurrentPage(0); UpdateButtonsByCurrentPage(0);
} }
@@ -166,12 +206,12 @@ public class Pagination: TemplatedControl
SyncQuickJumperValue(); SyncQuickJumperValue();
} }
} }
private void OnQuickJumpInputLostFocus(object sender, RoutedEventArgs e) private void OnQuickJumpInputLostFocus(object sender, RoutedEventArgs e)
{ {
SyncQuickJumperValue(); SyncQuickJumperValue();
} }
private void SyncQuickJumperValue() private void SyncQuickJumperValue()
{ {
if (_quickJumpInput is null) return; if (_quickJumpInput is null) return;
@@ -180,12 +220,14 @@ public class Pagination: TemplatedControl
value = Clamp(value.Value, 1, PageCount); value = Clamp(value.Value, 1, PageCount);
SetCurrentValue(CurrentPageProperty, value); SetCurrentValue(CurrentPageProperty, value);
_quickJumpInput?.SetCurrentValue(NumericIntUpDown.ValueProperty, null); _quickJumpInput?.SetCurrentValue(NumericIntUpDown.ValueProperty, null);
InvokeCommand();
} }
private void OnButtonClick(object? sender, RoutedEventArgs e) private void OnButtonClick(object? sender, RoutedEventArgs e)
{ {
var diff = Equals(sender, _previousButton) ? -1 : 1; var diff = Equals(sender, _previousButton) ? -1 : 1;
AddCurrentPage(diff); AddCurrentPage(diff);
InvokeCommand();
} }
private void InitializePanelButtons() private void InitializePanelButtons()
@@ -218,20 +260,21 @@ public class Pagination: TemplatedControl
CurrentPage = pageButton.Page; CurrentPage = pageButton.Page;
} }
} }
InvokeCommand();
} }
private void AddCurrentPage(int pageChange) private void AddCurrentPage(int pageChange)
{ {
int newValue = (CurrentPage ?? 0) + pageChange; int newValue = (CurrentPage ?? 0) + pageChange;
newValue = Clamp(newValue, 1, PageCount); newValue = Clamp(newValue, 1, PageCount);
; SetCurrentValue(CurrentPageProperty, newValue); SetCurrentValue(CurrentPageProperty, newValue);
} }
private int Clamp(int value, int min, int max) private int Clamp(int value, int min, int max)
{ {
return value < min ? min : value > max ? max : value; return value < min ? min : value > max ? max : value;
} }
/// <summary> /// <summary>
/// Update Button Content and Visibility by current page. /// Update Button Content and Visibility by current page.
/// </summary> /// </summary>
@@ -256,7 +299,7 @@ public class Pagination: TemplatedControl
if (i < pageCount) if (i < pageCount)
{ {
_buttons[i].IsVisible = true; _buttons[i].IsVisible = true;
_buttons[i].SetStatus(i + 1, i+1 == CurrentPage, false, false); _buttons[i].SetStatus(i + 1, i + 1 == CurrentPage, false, false);
} }
else else
{ {
@@ -277,21 +320,21 @@ public class Pagination: TemplatedControl
_buttons[4].Page = mid + 1; _buttons[4].Page = mid + 1;
_buttons[0].Page = 1; _buttons[0].Page = 1;
_buttons[6].Page = pageCount; _buttons[6].Page = pageCount;
if(mid>4) if (mid > 4)
{ {
_buttons[1].SetStatus(-1, false, true, false); _buttons[1].SetStatus(-1, false, true, false);
} }
else else
{ {
_buttons[1].SetStatus(mid-2, false, false, false); _buttons[1].SetStatus(mid - 2, false, false, false);
} }
if(mid<pageCount-3) if (mid < pageCount - 3)
{ {
_buttons[5].SetStatus(-1, false, false, true); _buttons[5].SetStatus(-1, false, false, true);
} }
else else
{ {
_buttons[5].SetStatus(mid+2, false, false, false); _buttons[5].SetStatus(mid + 2, false, false, false);
} }
foreach (var button in _buttons) foreach (var button in _buttons)
@@ -309,7 +352,14 @@ public class Pagination: TemplatedControl
PageCount = pageCount; PageCount = pageCount;
SetCurrentValue(CurrentPageProperty, currentPage); SetCurrentValue(CurrentPageProperty, currentPage);
if (_previousButton != null) _previousButton.IsEnabled = (CurrentPage??int.MaxValue) > 1; if (_previousButton != null) _previousButton.IsEnabled = (CurrentPage ?? int.MaxValue) > 1;
if (_nextButton != null) _nextButton.IsEnabled = (CurrentPage ?? 0) < PageCount; if (_nextButton != null) _nextButton.IsEnabled = (CurrentPage ?? 0) < PageCount;
} }
private void InvokeCommand()
{
if (this.Command != null && this.Command.CanExecute(this.CommandParameter))
{
this.Command.Execute(this.CommandParameter);
}
}
} }