diff --git a/demo/Ursa.Demo/Pages/PaginationDemo.axaml b/demo/Ursa.Demo/Pages/PaginationDemo.axaml
index 0037750..602c2da 100644
--- a/demo/Ursa.Demo/Pages/PaginationDemo.axaml
+++ b/demo/Ursa.Demo/Pages/PaginationDemo.axaml
@@ -13,11 +13,16 @@
-
+
+
+
+
+
diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
index aed7270..3c0765a 100644
--- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
@@ -34,7 +34,7 @@ public class MenuViewModel: ViewModelBase
// new() { MenuHeader = "Number Displayer", Key = MenuKeys.MenuKeyNumberDisplayer, Status = "New" },
new() { MenuHeader = "Numeric UpDown", Key = MenuKeys.MenuKeyNumericUpDown },
new() { MenuHeader = "NumPad", Key = MenuKeys.MenuKeyNumPad, Status = "New" },
- new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination },
+ new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination, Status = "Updated" },
new() { MenuHeader = "RangeSlider", Key = MenuKeys.MenuKeyRangeSlider },
new() { MenuHeader = "Scroll To", Key = MenuKeys.MenuKeyScrollToButton, Status = "New" },
new() { MenuHeader = "Selection List", Key = MenuKeys.MenuKeySelectionList, Status = "New" },
diff --git a/src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml b/src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml
index 31c1aa8..bb3cb95 100644
--- a/src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml
+++ b/src/Ursa.Themes.Semi/Controls/NumericUpDown.axaml
@@ -35,6 +35,7 @@
MinWidth="0"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
+ ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}"
AllowSpin="{TemplateBinding AllowSpin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
diff --git a/src/Ursa.Themes.Semi/Controls/Pagination.axaml b/src/Ursa.Themes.Semi/Controls/Pagination.axaml
index 0eaa096..8b1446d 100644
--- a/src/Ursa.Themes.Semi/Controls/Pagination.axaml
+++ b/src/Ursa.Themes.Semi/Controls/Pagination.axaml
@@ -12,7 +12,7 @@
-
+
-
+
+
+
+
+
+
-
-
-
+
+
+
diff --git a/src/Ursa.Themes.Semi/Locale/en-us.axaml b/src/Ursa.Themes.Semi/Locale/en-us.axaml
index e6d2f69..9940ce5 100644
--- a/src/Ursa.Themes.Semi/Locale/en-us.axaml
+++ b/src/Ursa.Themes.Semi/Locale/en-us.axaml
@@ -10,4 +10,6 @@
Yes
No
Close
+ Jump to page
+
diff --git a/src/Ursa.Themes.Semi/Locale/zh-cn.axaml b/src/Ursa.Themes.Semi/Locale/zh-cn.axaml
index c738313..d9a2c2b 100644
--- a/src/Ursa.Themes.Semi/Locale/zh-cn.axaml
+++ b/src/Ursa.Themes.Semi/Locale/zh-cn.axaml
@@ -10,4 +10,6 @@
是
否
关闭
+ 跳至
+ 页
diff --git a/src/Ursa/Controls/NumericUpDown/NumericUpDownBase.cs b/src/Ursa/Controls/NumericUpDown/NumericUpDownBase.cs
index a8dbd14..928fdfa 100644
--- a/src/Ursa/Controls/NumericUpDown/NumericUpDownBase.cs
+++ b/src/Ursa/Controls/NumericUpDown/NumericUpDownBase.cs
@@ -110,6 +110,15 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
set => SetValue(AllowSpinProperty, value);
}
+ public static readonly StyledProperty ShowButtonSpinnerProperty =
+ ButtonSpinner.ShowButtonSpinnerProperty.AddOwner();
+
+ public bool ShowButtonSpinner
+ {
+ get => GetValue(ShowButtonSpinnerProperty);
+ set => SetValue(ShowButtonSpinnerProperty, value);
+ }
+
public event EventHandler? Spinned;
static NumericUpDown()
diff --git a/src/Ursa/Controls/Pagination/Pagination.cs b/src/Ursa/Controls/Pagination/Pagination.cs
index f462496..a5bde53 100644
--- a/src/Ursa/Controls/Pagination/Pagination.cs
+++ b/src/Ursa/Controls/Pagination/Pagination.cs
@@ -3,8 +3,10 @@ using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
+using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Styling;
+using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
@@ -16,39 +18,23 @@ namespace Ursa.Controls;
[TemplatePart(PART_PreviousButton, typeof(PaginationButton))]
[TemplatePart(PART_NextButton, typeof(PaginationButton))]
[TemplatePart(PART_ButtonPanel, typeof(StackPanel))]
-[TemplatePart(PART_SizeChangerComboBox, typeof(ComboBox))]
+[TemplatePart(PART_QuickJumpInput, typeof(NumericIntUpDown))]
public class Pagination: TemplatedControl
{
public const string PART_PreviousButton = "PART_PreviousButton";
public const string PART_NextButton = "PART_NextButton";
public const string PART_ButtonPanel = "PART_ButtonPanel";
- public const string PART_SizeChangerComboBox = "PART_SizeChangerComboBox";
+ public const string PART_QuickJumpInput = "PART_QuickJumpInput";
private PaginationButton? _previousButton;
private PaginationButton? _nextButton;
private StackPanel? _buttonPanel;
private readonly PaginationButton[] _buttons = new PaginationButton[7];
- private ComboBox? _sizeChangerComboBox;
-
- protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
- {
- base.OnApplyTemplate(e);
- if (_previousButton != null) _previousButton.Click -= OnButtonClick;
- if (_nextButton != null) _nextButton.Click -= OnButtonClick;
- _previousButton = e.NameScope.Find(PART_PreviousButton);
- _nextButton = e.NameScope.Find(PART_NextButton);
- _buttonPanel = e.NameScope.Find(PART_ButtonPanel);
- _sizeChangerComboBox = e.NameScope.Find(PART_SizeChangerComboBox);
- if (_previousButton != null) _previousButton.Click += OnButtonClick;
- if (_nextButton != null) _nextButton.Click += OnButtonClick;
- InitializePanelButtons();
- UpdateButtons(0);
-
- }
+ private NumericIntUpDown? _quickJumpInput;
- public static readonly StyledProperty CurrentPageProperty = AvaloniaProperty.Register(
+ public static readonly StyledProperty CurrentPageProperty = AvaloniaProperty.Register(
nameof(CurrentPage));
- public int CurrentPage
+ public int? CurrentPage
{
get => GetValue(CurrentPageProperty);
set => SetValue(CurrentPageProperty, value);
@@ -121,40 +107,85 @@ public class Pagination: TemplatedControl
public static readonly StyledProperty ShowQuickJumpProperty = AvaloniaProperty.Register(
nameof(ShowQuickJump));
-
+
public bool ShowQuickJump
{
get => GetValue(ShowQuickJumpProperty);
set => SetValue(ShowQuickJumpProperty, value);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ static Pagination()
{
- base.OnPropertyChanged(change);
- // When page size is updated, the selected current page must be updated.
- if (change.Property == PageSizeProperty)
+ PageSizeProperty.Changed.AddClassHandler((pagination, args)=>pagination.OnPageSizeChanged(args));
+ CurrentPageProperty.Changed.AddClassHandler((pagination, args) =>
+ pagination.UpdateButtonsByCurrentPage(args.NewValue.Value));
+ TotalCountProperty.Changed.AddClassHandler((pagination, args) =>
+ pagination.UpdateButtonsByCurrentPage(pagination.CurrentPage));
+ }
+
+ private void OnPageSizeChanged(AvaloniaPropertyChangedEventArgs args)
+ {
+ int pageCount = TotalCount / args.NewValue.Value;
+ int residue = TotalCount % args.NewValue.Value;
+ if (residue > 0)
{
- int oldPageSize = change.GetOldValue();
- int index = oldPageSize * CurrentPage;
- UpdateButtons(index);
+ pageCount++;
}
- else if (change.Property == TotalCountProperty || change.Property == CurrentPageProperty)
+ PageCount = pageCount;
+ if (CurrentPage > PageCount)
{
- int index = PageSize * CurrentPage;
- UpdateButtons(index);
+ CurrentPage = null;
}
+ UpdateButtonsByCurrentPage(CurrentPage);
+ }
+
+ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+ {
+ base.OnApplyTemplate(e);
+
+ Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton);
+ _previousButton = e.NameScope.Find(PART_PreviousButton);
+ _nextButton = e.NameScope.Find(PART_NextButton);
+ _buttonPanel = e.NameScope.Find(PART_ButtonPanel);
+ Button.ClickEvent.AddHandler(OnButtonClick, _previousButton, _nextButton);
+
+ KeyDownEvent.RemoveHandler(OnQuickJumpInputKeyDown, _quickJumpInput);
+ LostFocusEvent.RemoveHandler(OnQuickJumpInputLostFocus, _quickJumpInput);
+ _quickJumpInput = e.NameScope.Find(PART_QuickJumpInput);
+ KeyDownEvent.AddHandler(OnQuickJumpInputKeyDown, _quickJumpInput);
+ LostFocusEvent.AddHandler(OnQuickJumpInputLostFocus, _quickJumpInput);
+
+ InitializePanelButtons();
+ UpdateButtonsByCurrentPage(0);
+ }
+
+ private void OnQuickJumpInputKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key is Key.Enter or Key.Return)
+ {
+ SyncQuickJumperValue();
+ }
+ }
+
+ private void OnQuickJumpInputLostFocus(object sender, RoutedEventArgs e)
+ {
+ SyncQuickJumperValue();
+ }
+
+ private void SyncQuickJumperValue()
+ {
+ if (_quickJumpInput is null) return;
+ var value = _quickJumpInput?.Value;
+ if (value is null) return;
+ value = Clamp(value.Value, 1, PageCount);
+ SetCurrentValue(CurrentPageProperty, value);
+ _quickJumpInput?.SetCurrentValue(NumericIntUpDown.ValueProperty, null);
}
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
- if (Equals(sender, _previousButton))
- {
- AddCurrentPage(-1);
- }
- else
- {
- AddCurrentPage(1);
- }
+ var diff = Equals(sender, _previousButton) ? -1 : 1;
+ AddCurrentPage(diff);
}
private void InitializePanelButtons()
@@ -166,7 +197,7 @@ public class Pagination: TemplatedControl
var button = new PaginationButton() { Page = i, IsVisible = true };
_buttonPanel.Children.Add(button);
_buttons![i - 1] = button;
- button.Click+= OnPageButtonClick;
+ Button.ClickEvent.AddHandler(OnPageButtonClick, button);
}
}
@@ -191,30 +222,32 @@ public class Pagination: TemplatedControl
private void AddCurrentPage(int pageChange)
{
- int newValue = CurrentPage + pageChange;
- if (newValue <= 0) newValue = 1;
- else if(newValue>=PageCount) newValue = PageCount;
- CurrentPage = newValue;
+ int newValue = (CurrentPage ?? 0) + pageChange;
+ newValue = Clamp(newValue, 1, PageCount);
+ ; SetCurrentValue(CurrentPageProperty, newValue);
}
-
- private void UpdateButtons(int index)
+
+ private int Clamp(int value, int min, int max)
+ {
+ return value < min ? min : value > max ? max : value;
+ }
+
+ ///
+ /// Update Button Content and Visibility by current page.
+ ///
+ ///
+ private void UpdateButtonsByCurrentPage(int? page)
{
if (_buttonPanel is null) return;
if (PageSize == 0) return;
- int currentIndex = index;
-
+ int? currentPage = CurrentPage;
int pageCount = TotalCount / PageSize;
int residue = TotalCount % PageSize;
if (residue > 0)
{
pageCount++;
}
-
- PageCount = pageCount;
-
- int currentPage = currentIndex/ PageSize;
- if (currentPage == 0) currentPage++;
if (pageCount <= 7)
{
@@ -237,9 +270,8 @@ public class Pagination: TemplatedControl
{
_buttons[i].IsVisible = true;
}
- int mid = currentPage;
- if (mid < 4) mid = 4;
- else if (mid > pageCount - 3) mid = pageCount - 3;
+ int mid = currentPage ?? 0;
+ mid = Clamp(mid, 4, pageCount - 3);
_buttons[3].Page = mid;
_buttons[2].Page = mid - 1;
_buttons[4].Page = mid + 1;
@@ -247,7 +279,7 @@ public class Pagination: TemplatedControl
_buttons[6].Page = pageCount;
if(mid>4)
{
- _buttons[1].SetStatus(0, false, true, false);
+ _buttons[1].SetStatus(-1, false, true, false);
}
else
{
@@ -255,7 +287,7 @@ public class Pagination: TemplatedControl
}
if(mid 1;
- if( _nextButton!=null) _nextButton.IsEnabled = CurrentPage < PageCount;
+ PageCount = pageCount;
+ SetCurrentValue(CurrentPageProperty, currentPage);
+ if (_previousButton != null) _previousButton.IsEnabled = (CurrentPage??int.MaxValue) > 1;
+ if (_nextButton != null) _nextButton.IsEnabled = (CurrentPage ?? 0) < PageCount;
}
}
\ No newline at end of file