mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-26 03:00:28 +08:00
Add SimplePagination
This commit is contained in:
+1
@@ -95,6 +95,7 @@
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SegmentedItemTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SegmentedTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SeparatorTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SimplePaginationTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SliderTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SliderThumbTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SplitButtonTheme());
|
||||
|
||||
-1
@@ -520,7 +520,6 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey PaginationLayoutSpacing = new TokenResourceKey("Pagination.PaginationLayoutSpacing");
|
||||
public static readonly TokenResourceKey PaginationMiniQuickJumperInputWidth = new TokenResourceKey("Pagination.PaginationMiniQuickJumperInputWidth");
|
||||
public static readonly TokenResourceKey PaginationQuickJumperInputWidth = new TokenResourceKey("Pagination.PaginationQuickJumperInputWidth");
|
||||
public static readonly TokenResourceKey PaginationSlashMarginInline = new TokenResourceKey("Pagination.PaginationSlashMarginInline");
|
||||
}
|
||||
|
||||
public static class PopupConfirmTokenKey
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public abstract class AbstractPagination : TemplatedControl,
|
||||
ISizeTypeAware,
|
||||
IMotionAwareControl,
|
||||
IResourceBindingManager
|
||||
{
|
||||
public const int DefaultPageSize = 10;
|
||||
public const int DefaultCurrentPage = 1;
|
||||
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<PaginationAlign> AlignProperty =
|
||||
AvaloniaProperty.Register<AbstractPagination, PaginationAlign>(nameof(PaginationAlign));
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<AbstractPagination>();
|
||||
|
||||
public static readonly DirectProperty<AbstractPagination, int> CurrentPageProperty =
|
||||
AvaloniaProperty.RegisterDirect<AbstractPagination, int>(nameof(CurrentPage),
|
||||
o => o.CurrentPage,
|
||||
(o, v) => o.CurrentPage = v,
|
||||
unsetValue: DefaultCurrentPage);
|
||||
|
||||
public static readonly DirectProperty<AbstractPagination, int> PageSizeProperty =
|
||||
AvaloniaProperty.RegisterDirect<AbstractPagination, int>(nameof(PageSize),
|
||||
o => o.PageSize,
|
||||
(o, v) => o.PageSize = v,
|
||||
unsetValue: DefaultPageSize,
|
||||
enableDataValidation:true);
|
||||
|
||||
public static readonly DirectProperty<AbstractPagination, long> TotalProperty =
|
||||
AvaloniaProperty.RegisterDirect<AbstractPagination, long>(nameof(Total),
|
||||
o => o.Total,
|
||||
(o, v) => o.Total = v);
|
||||
|
||||
public static readonly StyledProperty<bool> IsMotionEnabledProperty
|
||||
= WaveSpiritAwareControlProperty.IsMotionEnabledProperty.AddOwner<AbstractPagination>();
|
||||
|
||||
public PaginationAlign Align
|
||||
{
|
||||
get => GetValue(AlignProperty);
|
||||
set => SetValue(AlignProperty, value);
|
||||
}
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
|
||||
private protected int _currentPage = DefaultCurrentPage;
|
||||
public int CurrentPage
|
||||
{
|
||||
get => _currentPage;
|
||||
set => SetAndRaise(CurrentPageProperty, ref _currentPage, value);
|
||||
}
|
||||
|
||||
private protected int _pageSize = DefaultPageSize;
|
||||
public int PageSize
|
||||
{
|
||||
get => _pageSize;
|
||||
set
|
||||
{
|
||||
if (!new[] { 10, 20, 50, 100 }.Contains(value))
|
||||
{
|
||||
throw new ArgumentException("PageSize only allow: 10, 20, 50, 100");
|
||||
}
|
||||
SetAndRaise(PageSizeProperty, ref _pageSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
private protected long _total;
|
||||
public long Total
|
||||
{
|
||||
get => _total;
|
||||
set => SetAndRaise(TotalProperty, ref _total, value);
|
||||
}
|
||||
|
||||
public bool IsMotionEnabled
|
||||
{
|
||||
get => GetValue(IsMotionEnabledProperty);
|
||||
set => SetValue(IsMotionEnabledProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
public event EventHandler<PageChangedArgs>? CurrentPageChanged;
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
Control IMotionAwareControl.PropertyBindTarget => this;
|
||||
CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable;
|
||||
private CompositeDisposable? _resourceBindingsDisposable;
|
||||
#endregion
|
||||
|
||||
static AbstractPagination()
|
||||
{
|
||||
AffectsMeasure<AbstractPagination>(SizeTypeProperty);
|
||||
}
|
||||
|
||||
public AbstractPagination()
|
||||
{
|
||||
this.BindMotionProperties();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (this.IsAttachedToVisualTree())
|
||||
{
|
||||
if (change.Property == TotalProperty ||
|
||||
change.Property == PageSizeProperty ||
|
||||
change.Property == CurrentPageProperty)
|
||||
{
|
||||
HandlePageConditionChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void HandlePageConditionChanged()
|
||||
{
|
||||
var total = Math.Max(0, Total);
|
||||
var pageSize = PageSize <= 0 ? DefaultPageSize : PageSize;
|
||||
var pageCount = (int)Math.Ceiling(total / (double)pageSize);
|
||||
var currentPage = Math.Max(1, Math.Min(CurrentPage, pageCount));
|
||||
_currentPage = currentPage;
|
||||
NotifyPageConditionChanged(currentPage, pageCount, pageSize, total);
|
||||
}
|
||||
|
||||
protected virtual void NotifyPageConditionChanged(int currentPage, int pageCount, int pageSize, long total)
|
||||
{
|
||||
}
|
||||
|
||||
protected void EmitCurrentPageChanged(int currentPage, int pageCount, int pageSize)
|
||||
{
|
||||
CurrentPageChanged?.Invoke(this, new PageChangedArgs(currentPage, pageCount, pageSize));
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_resourceBindingsDisposable = new CompositeDisposable();
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
this.DisposeTokenBindings();
|
||||
}
|
||||
}
|
||||
@@ -23,42 +23,13 @@ public enum PaginationAlign
|
||||
End
|
||||
}
|
||||
|
||||
public class Pagination : TemplatedControl,
|
||||
ISizeTypeAware,
|
||||
IMotionAwareControl,
|
||||
IControlSharedTokenResourcesHost,
|
||||
IResourceBindingManager
|
||||
public class Pagination : AbstractPagination,
|
||||
IControlSharedTokenResourcesHost
|
||||
{
|
||||
public const int DefaultPageSize = 10;
|
||||
public const int DefaultCurrentPage = 1;
|
||||
internal const int MaxNavItemCount = 11;
|
||||
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<PaginationAlign> AlignProperty =
|
||||
AvaloniaProperty.Register<Button, PaginationAlign>(nameof(PaginationAlign));
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<Pagination>();
|
||||
|
||||
public static readonly DirectProperty<Pagination, int> CurrentPageProperty =
|
||||
AvaloniaProperty.RegisterDirect<Pagination, int>(nameof(CurrentPage),
|
||||
o => o.CurrentPage,
|
||||
(o, v) => o.CurrentPage = v,
|
||||
unsetValue: DefaultCurrentPage);
|
||||
|
||||
public static readonly DirectProperty<Pagination, int> PageSizeProperty =
|
||||
AvaloniaProperty.RegisterDirect<Pagination, int>(nameof(PageSize),
|
||||
o => o.PageSize,
|
||||
(o, v) => o.PageSize = v,
|
||||
unsetValue: DefaultPageSize,
|
||||
enableDataValidation:true);
|
||||
|
||||
public static readonly DirectProperty<Pagination, long> TotalProperty =
|
||||
AvaloniaProperty.RegisterDirect<Pagination, long>(nameof(Total),
|
||||
o => o.Total,
|
||||
(o, v) => o.Total = v);
|
||||
|
||||
public static readonly DirectProperty<Pagination, bool> HideOnSinglePageProperty =
|
||||
AvaloniaProperty.RegisterDirect<Pagination, bool>(nameof(HideOnSinglePage),
|
||||
o => o.HideOnSinglePage,
|
||||
@@ -82,49 +53,6 @@ public class Pagination : TemplatedControl,
|
||||
public static readonly StyledProperty<string?> TotalInfoTemplateProperty =
|
||||
AvaloniaProperty.Register<Pagination, string?>(nameof(TotalInfoTemplate));
|
||||
|
||||
public static readonly StyledProperty<bool> IsMotionEnabledProperty
|
||||
= WaveSpiritAwareControlProperty.IsMotionEnabledProperty.AddOwner<Pagination>();
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
|
||||
public PaginationAlign Align
|
||||
{
|
||||
get => GetValue(AlignProperty);
|
||||
set => SetValue(AlignProperty, value);
|
||||
}
|
||||
|
||||
private int _currentPage = DefaultCurrentPage;
|
||||
public int CurrentPage
|
||||
{
|
||||
get => _currentPage;
|
||||
set => SetAndRaise(CurrentPageProperty, ref _currentPage, value);
|
||||
}
|
||||
|
||||
private int _pageSize = DefaultPageSize;
|
||||
public int PageSize
|
||||
{
|
||||
get => _pageSize;
|
||||
set
|
||||
{
|
||||
if (!new[] { 10, 20, 50, 100 }.Contains(value))
|
||||
{
|
||||
throw new ArgumentException("PageSize only allow: 10, 20, 50, 100");
|
||||
}
|
||||
SetAndRaise(PageSizeProperty, ref _pageSize, value);
|
||||
}
|
||||
}
|
||||
|
||||
private long _total;
|
||||
public long Total
|
||||
{
|
||||
get => _total;
|
||||
set => SetAndRaise(TotalProperty, ref _total, value);
|
||||
}
|
||||
|
||||
private bool _hideOnSinglePage;
|
||||
public bool HideOnSinglePage
|
||||
{
|
||||
@@ -159,15 +87,6 @@ public class Pagination : TemplatedControl,
|
||||
set => SetValue(TotalInfoTemplateProperty, value);
|
||||
}
|
||||
|
||||
public bool IsMotionEnabled
|
||||
{
|
||||
get => GetValue(IsMotionEnabledProperty);
|
||||
set => SetValue(IsMotionEnabledProperty, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
public event EventHandler<PageChangedArgs>? CurrentPageChanged;
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
@@ -220,11 +139,8 @@ public class Pagination : TemplatedControl,
|
||||
set => SetAndRaise(TotalInfoTextProperty, ref _totalInfoText, value);
|
||||
}
|
||||
|
||||
Control IMotionAwareControl.PropertyBindTarget => this;
|
||||
Control IControlSharedTokenResourcesHost.HostControl => this;
|
||||
string IControlSharedTokenResourcesHost.TokenId => PaginationToken.ID;
|
||||
CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable;
|
||||
private CompositeDisposable? _resourceBindingsDisposable;
|
||||
#endregion
|
||||
|
||||
private PaginationNav? _paginationNav;
|
||||
@@ -233,15 +149,9 @@ public class Pagination : TemplatedControl,
|
||||
private int _nextPushItemIndex = 1;
|
||||
private int _selectedNavItemIndex = -1;
|
||||
|
||||
static Pagination()
|
||||
{
|
||||
AffectsMeasure<Button>(SizeTypeProperty);
|
||||
}
|
||||
|
||||
public Pagination()
|
||||
{
|
||||
this.RegisterResources();
|
||||
this.BindMotionProperties();
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
@@ -257,7 +167,6 @@ public class Pagination : TemplatedControl,
|
||||
{
|
||||
SetupQuickJumper();
|
||||
}
|
||||
|
||||
if (ShowSizeChanger)
|
||||
{
|
||||
SetupSizeChanger();
|
||||
@@ -292,14 +201,9 @@ public class Pagination : TemplatedControl,
|
||||
HandlePageConditionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePageConditionChanged()
|
||||
|
||||
protected override void NotifyPageConditionChanged(int currentPage, int pageCount, int pageSize, long total)
|
||||
{
|
||||
var total = Math.Max(0, Total);
|
||||
var pageSize = PageSize <= 0 ? DefaultPageSize : PageSize;
|
||||
var pageCount = (int)Math.Ceiling(total / (double)pageSize);
|
||||
var currentPage = Math.Max(1, Math.Min(CurrentPage, pageCount));
|
||||
_currentPage = currentPage;
|
||||
Debug.Assert(_paginationNav != null);
|
||||
Debug.Assert(_previousPageItem != null);
|
||||
Debug.Assert(_nextPageItem != null);
|
||||
@@ -329,7 +233,7 @@ public class Pagination : TemplatedControl,
|
||||
SetupRightButtonRange(currentPage, pageCount);
|
||||
_paginationNav.SelectedIndex = _selectedNavItemIndex;
|
||||
SetupTotalInfoText();
|
||||
CurrentPageChanged?.Invoke(this, new PageChangedArgs(CurrentPage, pageCount, pageSize));
|
||||
EmitCurrentPageChanged(CurrentPage, pageCount, pageSize);
|
||||
}
|
||||
|
||||
private void HandlePageNavRequest(object? sender, PageNavRequestArgs args)
|
||||
@@ -426,13 +330,7 @@ public class Pagination : TemplatedControl,
|
||||
base.OnPropertyChanged(change);
|
||||
if (this.IsAttachedToVisualTree())
|
||||
{
|
||||
if (change.Property == TotalProperty ||
|
||||
change.Property == PageSizeProperty ||
|
||||
change.Property == CurrentPageProperty)
|
||||
{
|
||||
HandlePageConditionChanged();
|
||||
}
|
||||
else if (change.Property == ShowSizeChangerProperty)
|
||||
if (change.Property == ShowSizeChangerProperty)
|
||||
{
|
||||
SetupSizeChanger();
|
||||
}
|
||||
@@ -517,16 +415,4 @@ public class Pagination : TemplatedControl,
|
||||
PageSize = Math.Max(comboBoxItem.PageSize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_resourceBindingsDisposable = new CompositeDisposable();
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
this.DisposeTokenBindings();
|
||||
}
|
||||
}
|
||||
@@ -104,9 +104,36 @@ internal class PaginationTheme : BaseControlTheme
|
||||
alignStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Right);
|
||||
commonStyle.Add(alignStyle);
|
||||
}
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutSpacing);
|
||||
commonStyle.Add(layoutStyle);
|
||||
|
||||
|
||||
var largeSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Large));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutSpacing);
|
||||
largeSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
|
||||
commonStyle.Add(largeSizeStyle);
|
||||
|
||||
var middleSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Middle));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutSpacing);
|
||||
middleSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
commonStyle.Add(middleSizeStyle);
|
||||
|
||||
var smallSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Small));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutMiniSpacing);
|
||||
smallSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
commonStyle.Add(smallSizeStyle);
|
||||
|
||||
Add(commonStyle);
|
||||
}
|
||||
}
|
||||
@@ -93,12 +93,6 @@ internal class PaginationToken : AbstractControlDesignToken
|
||||
/// </summary>
|
||||
public Thickness PaginationItemPaddingInline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 斜杠横向外边距
|
||||
/// Horizontal margin of slash
|
||||
/// </summary>
|
||||
public Thickness PaginationSlashMarginInline { get; set; }
|
||||
|
||||
public PaginationToken()
|
||||
: base(ID)
|
||||
{
|
||||
@@ -123,6 +117,5 @@ internal class PaginationToken : AbstractControlDesignToken
|
||||
PaginationQuickJumperInputWidth = SharedToken.ControlHeightLG * 1.25;
|
||||
PaginationMiniQuickJumperInputWidth = SharedToken.ControlHeightLG * 1.1;
|
||||
PaginationItemPaddingInline = new Thickness(SharedToken.MarginXXS * 1.5);
|
||||
PaginationSlashMarginInline = new Thickness(SharedToken.MarginXXS, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,125 @@
|
||||
using System.Diagnostics;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SimplePagination
|
||||
public class SimplePagination : AbstractPagination,
|
||||
IControlSharedTokenResourcesHost
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<bool> IsReadOnlyProperty =
|
||||
AvaloniaProperty.Register<AbstractPagination, bool>(nameof(PaginationAlign), defaultValue:true);
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get => GetValue(IsReadOnlyProperty);
|
||||
set => SetValue(IsReadOnlyProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
Control IControlSharedTokenResourcesHost.HostControl => this;
|
||||
string IControlSharedTokenResourcesHost.TokenId => PaginationToken.ID;
|
||||
|
||||
#endregion
|
||||
|
||||
private PaginationNavItem? _previousPageItem;
|
||||
private PaginationNavItem? _nextPageItem;
|
||||
private TextBlock? _infoIndicator;
|
||||
private LineEdit? _quickJumper;
|
||||
|
||||
static SimplePagination()
|
||||
{
|
||||
AffectsMeasure<SimplePagination>(IsReadOnlyProperty);
|
||||
}
|
||||
|
||||
public SimplePagination()
|
||||
{
|
||||
this.RegisterResources();
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_previousPageItem = e.NameScope.Find<PaginationNavItem>(SimplePaginationTheme.PreviousNavItemPart);
|
||||
_nextPageItem = e.NameScope.Find<PaginationNavItem>(SimplePaginationTheme.NextNavItemPart);
|
||||
_infoIndicator = e.NameScope.Find<TextBlock>(SimplePaginationTheme.InfoIndicatorPart);
|
||||
_quickJumper = e.NameScope.Find<LineEdit>(SimplePaginationTheme.QuickJumperPart);
|
||||
|
||||
Debug.Assert(_nextPageItem != null);
|
||||
Debug.Assert(_previousPageItem != null);
|
||||
Debug.Assert(_quickJumper != null);
|
||||
_previousPageItem.Click += HandleNavItemClicked;
|
||||
_nextPageItem.Click += HandleNavItemClicked;
|
||||
_quickJumper.KeyUp += HandleLineEditKeyUp;
|
||||
|
||||
HandlePageConditionChanged();
|
||||
}
|
||||
|
||||
protected override void NotifyPageConditionChanged(int currentPage, int pageCount, int pageSize, long total)
|
||||
{
|
||||
if (IsReadOnly)
|
||||
{
|
||||
if (_infoIndicator != null)
|
||||
{
|
||||
_infoIndicator.Text = $"{currentPage} / {pageCount}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_infoIndicator != null)
|
||||
{
|
||||
_infoIndicator.Text = $" / {pageCount}";
|
||||
}
|
||||
|
||||
if (_quickJumper != null)
|
||||
{
|
||||
_quickJumper.Text = $"{currentPage}";
|
||||
}
|
||||
}
|
||||
Debug.Assert(_previousPageItem != null);
|
||||
Debug.Assert(_nextPageItem != null);
|
||||
|
||||
_previousPageItem.IsEnabled = currentPage > 1;
|
||||
_previousPageItem.PageNumber = Math.Max(1, CurrentPage - 1);
|
||||
_nextPageItem.IsEnabled = currentPage < pageCount;
|
||||
_nextPageItem.PageNumber = Math.Min(pageCount, CurrentPage + 1);
|
||||
EmitCurrentPageChanged(CurrentPage, pageCount, pageSize);
|
||||
}
|
||||
|
||||
private void HandleNavItemClicked(object? sender, RoutedEventArgs args)
|
||||
{
|
||||
if (sender is PaginationNavItem navItemSender)
|
||||
{
|
||||
CurrentPage = navItemSender.PageNumber;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLineEditKeyUp(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (sender is LineEdit lineEdit)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
if (int.TryParse(lineEdit.Text?.Trim(), out var pageNumber))
|
||||
{
|
||||
var pageCount = (int)Math.Ceiling(Total / (double)PageSize);
|
||||
CurrentPage = Math.Max(1, Math.Min(pageNumber, pageCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
lineEdit.Text = $"{CurrentPage}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using AtomUI.IconPkg.AntDesign;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class SimplePaginationTheme : BaseControlTheme
|
||||
{
|
||||
public const string RootLayoutPart = "PART_RootLayoutPart";
|
||||
public const string PreviousNavItemPart = "PART_PreviousNavItem";
|
||||
public const string NextNavItemPart = "PART_NextNavItem";
|
||||
public const string InfoIndicatorPart = "PART_InfoIndicator";
|
||||
public const string QuickJumperPart = "PART_QuickJumper";
|
||||
|
||||
public SimplePaginationTheme()
|
||||
: base(typeof(SimplePagination))
|
||||
{
|
||||
}
|
||||
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<SimplePagination>((simplePagination, scope) =>
|
||||
{
|
||||
var mainLayout = new StackPanel()
|
||||
{
|
||||
Name = RootLayoutPart,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Orientation = Orientation.Horizontal,
|
||||
};
|
||||
|
||||
var previousNavItem = new PaginationNavItem()
|
||||
{
|
||||
Name = PreviousNavItemPart,
|
||||
PaginationItemType = PaginationItemType.Previous,
|
||||
Content = AntDesignIconPackage.LeftOutlined()
|
||||
};
|
||||
CreateTemplateParentBinding(previousNavItem, PaginationNavItem.SizeTypeProperty, SimplePagination.SizeTypeProperty);
|
||||
CreateTemplateParentBinding(previousNavItem, PaginationNavItem.IsEnabledProperty, SimplePagination.IsEnabledProperty);
|
||||
previousNavItem.RegisterInNameScope(scope);
|
||||
mainLayout.Children.Add(previousNavItem);
|
||||
|
||||
var quickJumperPart = new LineEdit()
|
||||
{
|
||||
Name = QuickJumperPart
|
||||
};
|
||||
CreateTemplateParentBinding(quickJumperPart,
|
||||
LineEdit.IsVisibleProperty,
|
||||
SimplePagination.IsReadOnlyProperty,
|
||||
BindingMode.Default,
|
||||
BoolConverters.Not);
|
||||
CreateTemplateParentBinding(quickJumperPart, LineEdit.SizeTypeProperty, SimplePagination.SizeTypeProperty);
|
||||
CreateTemplateParentBinding(quickJumperPart, LineEdit.IsEnabledProperty, SimplePagination.IsEnabledProperty);
|
||||
quickJumperPart.RegisterInNameScope(scope);
|
||||
mainLayout.Children.Add(quickJumperPart);
|
||||
|
||||
var infoIndicator = new TextBlock()
|
||||
{
|
||||
Name = InfoIndicatorPart,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
HorizontalAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
infoIndicator.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(infoIndicator, TextBlock.IsEnabledProperty, SimplePagination.IsEnabledProperty);
|
||||
mainLayout.Children.Add(infoIndicator);
|
||||
|
||||
var nextNavItem = new PaginationNavItem()
|
||||
{
|
||||
Name = NextNavItemPart,
|
||||
PaginationItemType = PaginationItemType.Next,
|
||||
Content = AntDesignIconPackage.RightOutlined()
|
||||
};
|
||||
CreateTemplateParentBinding(nextNavItem, PaginationNavItem.IsEnabledProperty, SimplePagination.IsEnabledProperty);
|
||||
CreateTemplateParentBinding(nextNavItem, PaginationNavItem.SizeTypeProperty, SimplePagination.SizeTypeProperty);
|
||||
nextNavItem.RegisterInNameScope(scope);
|
||||
mainLayout.Children.Add(nextNavItem);
|
||||
return mainLayout;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
var commonStyle = new Style(selector => selector.Nesting());
|
||||
|
||||
var largeSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Large));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutSpacing);
|
||||
largeSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
|
||||
commonStyle.Add(largeSizeStyle);
|
||||
|
||||
var middleSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Middle));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutSpacing);
|
||||
middleSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
commonStyle.Add(middleSizeStyle);
|
||||
|
||||
var smallSizeStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(PaginationNavItem.SizeTypeProperty, SizeType.Small));
|
||||
{
|
||||
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||
layoutStyle.Add(StackPanel.SpacingProperty, PaginationTokenKey.PaginationLayoutMiniSpacing);
|
||||
smallSizeStyle.Add(layoutStyle);
|
||||
}
|
||||
commonStyle.Add(smallSizeStyle);
|
||||
|
||||
var quickJumperStyle = new Style(selector => selector.Nesting().Template().Name(QuickJumperPart));
|
||||
quickJumperStyle.Add(LineEdit.MinWidthProperty, PaginationTokenKey.PaginationQuickJumperInputWidth);
|
||||
commonStyle.Add(quickJumperStyle);
|
||||
|
||||
Add(commonStyle);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user