using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls;
///
/// 页码
///
[TemplatePart(Name = ElementButtonLeft, Type = typeof(Button))]
[TemplatePart(Name = ElementButtonRight, Type = typeof(Button))]
[TemplatePart(Name = ElementButtonFirst, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementMoreLeft, Type = typeof(FrameworkElement))]
[TemplatePart(Name = ElementPanelMain, Type = typeof(Panel))]
[TemplatePart(Name = ElementMoreRight, Type = typeof(FrameworkElement))]
[TemplatePart(Name = ElementButtonLast, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonLast, Type = typeof(NumericUpDown))]
public class Pagination : Control
{
#region Constants
private const string ElementButtonLeft = "PART_ButtonLeft";
private const string ElementButtonRight = "PART_ButtonRight";
private const string ElementButtonFirst = "PART_ButtonFirst";
private const string ElementMoreLeft = "PART_MoreLeft";
private const string ElementPanelMain = "PART_PanelMain";
private const string ElementMoreRight = "PART_MoreRight";
private const string ElementButtonLast = "PART_ButtonLast";
private const string ElementJump = "PART_Jump";
#endregion Constants
#region Data
private Button _buttonLeft;
private Button _buttonRight;
private RadioButton _buttonFirst;
private FrameworkElement _moreLeft;
private Panel _panelMain;
private FrameworkElement _moreRight;
private RadioButton _buttonLast;
private NumericUpDown _jumpNumericUpDown;
private bool _appliedTemplate;
#endregion Data
#region Public Events
///
/// 页面更新事件
///
public static readonly RoutedEvent PageUpdatedEvent =
EventManager.RegisterRoutedEvent("PageUpdated", RoutingStrategy.Bubble,
typeof(EventHandler>), typeof(Pagination));
///
/// 页面更新事件
///
public event EventHandler> PageUpdated
{
add => AddHandler(PageUpdatedEvent, value);
remove => RemoveHandler(PageUpdatedEvent, value);
}
#endregion Public Events
public Pagination()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Prev, ButtonPrev_OnClick));
CommandBindings.Add(new CommandBinding(ControlCommands.Next, ButtonNext_OnClick));
CommandBindings.Add(new CommandBinding(ControlCommands.Selected, ToggleButton_OnChecked));
CommandBindings.Add(new CommandBinding(ControlCommands.Jump, (s, e) => PageIndex = (int) _jumpNumericUpDown.Value));
OnAutoHidingChanged(AutoHiding);
Update();
}
#region Public Properties
#region MaxPageCount
///
/// 最大页数
///
public static readonly DependencyProperty MaxPageCountProperty = DependencyProperty.Register(
nameof(MaxPageCount), typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnMaxPageCountChanged, CoerceMaxPageCount), ValidateHelper.IsInRangeOfPosIntIncludeZero);
private static object CoerceMaxPageCount(DependencyObject d, object basevalue)
{
var intValue = (int) basevalue;
return intValue < 1 ? 1 : intValue;
}
private static void OnMaxPageCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Pagination pagination)
{
if (pagination.PageIndex > pagination.MaxPageCount)
{
pagination.PageIndex = pagination.MaxPageCount;
}
pagination.CoerceValue(PageIndexProperty);
pagination.OnAutoHidingChanged(pagination.AutoHiding);
pagination.Update();
}
}
///
/// 最大页数
///
public int MaxPageCount
{
get => (int) GetValue(MaxPageCountProperty);
set => SetValue(MaxPageCountProperty, value);
}
#endregion MaxPageCount
#region DataCountPerPage
///
/// 每页的数据量
///
public static readonly DependencyProperty DataCountPerPageProperty = DependencyProperty.Register(
nameof(DataCountPerPage), typeof(int), typeof(Pagination), new PropertyMetadata(20, OnDataCountPerPageChanged),
ValidateHelper.IsInRangeOfPosInt);
private static void OnDataCountPerPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Pagination pagination)
{
pagination.Update();
}
}
///
/// 每页的数据量
///
public int DataCountPerPage
{
get => (int) GetValue(DataCountPerPageProperty);
set => SetValue(DataCountPerPageProperty, value);
}
#endregion
#region PageIndex
///
/// 当前页
///
public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register(
nameof(PageIndex), typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnPageIndexChanged, CoercePageIndex), ValidateHelper.IsInRangeOfPosIntIncludeZero);
private static object CoercePageIndex(DependencyObject d, object basevalue)
{
if (d is not Pagination pagination) return 1;
var intValue = (int) basevalue;
return intValue < 1
? 1
: intValue > pagination.MaxPageCount
? pagination.MaxPageCount
: intValue;
}
private static void OnPageIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Pagination pagination && e.NewValue is int value)
{
pagination.Update();
pagination.RaiseEvent(new FunctionEventArgs(PageUpdatedEvent, pagination)
{
Info = value
});
}
}
///
/// 当前页
///
public int PageIndex
{
get => (int) GetValue(PageIndexProperty);
set => SetValue(PageIndexProperty, value);
}
#endregion PageIndex
#region MaxPageInterval
///
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
///
public static readonly DependencyProperty MaxPageIntervalProperty = DependencyProperty.Register(
nameof(MaxPageInterval), typeof(int), typeof(Pagination), new PropertyMetadata(3, OnMaxPageIntervalChanged), ValidateHelper.IsInRangeOfPosIntIncludeZero);
private static void OnMaxPageIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Pagination pagination)
{
pagination.Update();
}
}
///
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
///
public int MaxPageInterval
{
get => (int) GetValue(MaxPageIntervalProperty);
set => SetValue(MaxPageIntervalProperty, value);
}
#endregion MaxPageInterval
#region IsJumpEnabled
public static readonly DependencyProperty IsJumpEnabledProperty = DependencyProperty.Register(
nameof(IsJumpEnabled), typeof(bool), typeof(Pagination), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsJumpEnabled
{
get => (bool) GetValue(IsJumpEnabledProperty);
set => SetValue(IsJumpEnabledProperty, ValueBoxes.BooleanBox(value));
}
#endregion
#region AutoHiding
public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
nameof(AutoHiding), typeof(bool), typeof(Pagination), new PropertyMetadata(ValueBoxes.TrueBox, OnAutoHidingChanged));
private static void OnAutoHidingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Pagination pagination)
{
pagination.OnAutoHidingChanged((bool) e.NewValue);
}
}
private void OnAutoHidingChanged(bool newValue) => this.Show(!newValue || MaxPageCount > 1);
public bool AutoHiding
{
get => (bool) GetValue(AutoHidingProperty);
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
}
#endregion
public static readonly DependencyProperty PaginationButtonStyleProperty = DependencyProperty.Register(
nameof(PaginationButtonStyle), typeof(Style), typeof(Pagination), new PropertyMetadata(default(Style)));
public Style PaginationButtonStyle
{
get => (Style) GetValue(PaginationButtonStyleProperty);
set => SetValue(PaginationButtonStyleProperty, value);
}
#endregion
#region Public Methods
public override void OnApplyTemplate()
{
_appliedTemplate = false;
base.OnApplyTemplate();
_buttonLeft = GetTemplateChild(ElementButtonLeft) as Button;
_buttonRight = GetTemplateChild(ElementButtonRight) as Button;
_buttonFirst = GetTemplateChild(ElementButtonFirst) as RadioButton;
_moreLeft = GetTemplateChild(ElementMoreLeft) as FrameworkElement;
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
_moreRight = GetTemplateChild(ElementMoreRight) as FrameworkElement;
_buttonLast = GetTemplateChild(ElementButtonLast) as RadioButton;
_jumpNumericUpDown = GetTemplateChild(ElementJump) as NumericUpDown;
CheckNull();
_appliedTemplate = true;
Update();
}
#endregion Public Methods
#region Private Methods
private void CheckNull()
{
if (_buttonLeft == null || _buttonRight == null || _buttonFirst == null ||
_moreLeft == null || _panelMain == null || _moreRight == null ||
_buttonLast == null) throw new Exception();
}
///
/// 更新
///
private void Update()
{
if (!_appliedTemplate) return;
_buttonLeft.IsEnabled = PageIndex > 1;
_buttonRight.IsEnabled = PageIndex < MaxPageCount;
if (MaxPageInterval == 0)
{
_buttonFirst.Collapse();
_buttonLast.Collapse();
_moreLeft.Collapse();
_moreRight.Collapse();
_panelMain.Children.Clear();
var selectButton = CreateButton(PageIndex);
_panelMain.Children.Add(selectButton);
selectButton.IsChecked = true;
return;
}
_buttonFirst.Show();
_buttonLast.Show();
_moreLeft.Show();
_moreRight.Show();
//更新最后一页
if (MaxPageCount == 1)
{
_buttonLast.Collapse();
}
else
{
_buttonLast.Show();
_buttonLast.Content = MaxPageCount.ToString();
}
//更新省略号
var right = MaxPageCount - PageIndex;
var left = PageIndex - 1;
_moreRight.Show(right > MaxPageInterval);
_moreLeft.Show(left > MaxPageInterval);
//更新中间部分
_panelMain.Children.Clear();
if (PageIndex > 1 && PageIndex < MaxPageCount)
{
var selectButton = CreateButton(PageIndex);
_panelMain.Children.Add(selectButton);
selectButton.IsChecked = true;
}
else if (PageIndex == 1)
{
_buttonFirst.IsChecked = true;
}
else
{
_buttonLast.IsChecked = true;
}
var sub = PageIndex;
for (var i = 0; i < MaxPageInterval - 1; i++)
{
if (--sub > 1)
{
_panelMain.Children.Insert(0, CreateButton(sub));
}
else
{
break;
}
}
var add = PageIndex;
for (var i = 0; i < MaxPageInterval - 1; i++)
{
if (++add < MaxPageCount)
{
_panelMain.Children.Add(CreateButton(add));
}
else
{
break;
}
}
}
private void ButtonPrev_OnClick(object sender, RoutedEventArgs e) => PageIndex--;
private void ButtonNext_OnClick(object sender, RoutedEventArgs e) => PageIndex++;
private RadioButton CreateButton(int page)
{
return new()
{
Style = PaginationButtonStyle,
Content = page.ToString()
};
}
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is not RadioButton button) return;
if (button.IsChecked == false) return;
PageIndex = int.Parse(button.Content.ToString());
}
#endregion Private Methods
}