Files
HandyControl/Net40/HandyControl_Net40/Controls/Other/Pagination.cs
T
2019-01-21 11:12:38 +08:00

363 lines
12 KiB
C#

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
{
/// <summary>
/// 页码
/// </summary>
[TemplatePart(Name = ElementButtonLeft, Type = typeof(Button))]
[TemplatePart(Name = ElementButtonRight, Type = typeof(Button))]
[TemplatePart(Name = ElementButtonFirst, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementTextBlockLeft, Type = typeof(TextBlock))]
[TemplatePart(Name = ElementPanelMain, Type = typeof(Panel))]
[TemplatePart(Name = ElementTextBlockRight, Type = typeof(TextBlock))]
[TemplatePart(Name = ElementButtonLast, Type = typeof(RadioButton))]
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 ElementTextBlockLeft = "PART_TextBlockLeft";
private const string ElementPanelMain = "PART_PanelMain";
private const string ElementTextBlockRight = "PART_TextBlockRight";
private const string ElementButtonLast = "PART_ButtonLast";
#endregion Constants
#region Data
private Button _buttonLeft;
private Button _buttonRight;
private RadioButton _buttonFirst;
private TextBlock _textBlockLeft;
private Panel _panelMain;
private TextBlock _textBlockRight;
private RadioButton _buttonLast;
private bool _appliedTemplate;
#endregion Data
#region Public Events
/// <summary>
/// 页面更新事件
/// </summary>
public static readonly RoutedEvent PageUpdatedEvent =
EventManager.RegisterRoutedEvent("PageUpdated", RoutingStrategy.Bubble,
typeof(EventHandler<FunctionEventArgs<int>>), typeof(Pagination));
/// <summary>
/// 页面更新事件
/// </summary>
public event EventHandler<FunctionEventArgs<int>> 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));
}
#region Public Properties
#region MaxPageCount
/// <summary>
/// 最大页数
/// </summary>
public static readonly DependencyProperty MaxPageCountProperty = DependencyProperty.Register(
"MaxPageCount", typeof(int), typeof(Pagination), new PropertyMetadata(1, (o, args) =>
{
if (o is Pagination pagination && args.NewValue is int value)
{
if (pagination.PageIndex > pagination.MaxPageCount)
{
pagination.PageIndex = pagination.MaxPageCount;
}
pagination.Show(value > 1);
pagination.Update();
}
}, (o, value) =>
{
if (!(o is Pagination)) return 1;
var intValue = (int)value;
if (intValue < 1)
{
return 1;
}
return intValue;
}));
/// <summary>
/// 最大页数
/// </summary>
public int MaxPageCount
{
get => (int)GetValue(MaxPageCountProperty);
set => SetValue(MaxPageCountProperty, value);
}
#endregion MaxPageCount
#region DataCountPerPage
/// <summary>
/// 每页的数据量
/// </summary>
public static readonly DependencyProperty DataCountPerPageProperty = DependencyProperty.Register(
"DataCountPerPage", typeof(int), typeof(Pagination), new PropertyMetadata(20, (o, args) =>
{
if (o is Pagination pagination)
{
pagination.Update();
}
}, (o, value) =>
{
if (!(o is Pagination)) return 1;
var intValue = (int)value;
if (intValue < 1)
{
return 1;
}
return intValue;
}));
/// <summary>
/// 每页的数据量
/// </summary>
public int DataCountPerPage
{
get => (int)GetValue(DataCountPerPageProperty);
set => SetValue(DataCountPerPageProperty, value);
}
#endregion
#region PageIndex
/// <summary>
/// 当前页
/// </summary>
public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register(
"PageIndex", typeof(int), typeof(Pagination), new PropertyMetadata(1, (o, args) =>
{
if (o is Pagination pagination && args.NewValue is int value)
{
pagination.Update();
pagination.RaiseEvent(new FunctionEventArgs<int>(PageUpdatedEvent, pagination)
{
Info = value
});
}
}, (o, value) =>
{
if (!(o is Pagination pagination)) return 1;
var intValue = (int)value;
if (intValue < 0)
{
return 0;
}
if (intValue > pagination.MaxPageCount) return pagination.MaxPageCount;
return intValue;
}));
/// <summary>
/// 当前页
/// </summary>
public int PageIndex
{
get => (int)GetValue(PageIndexProperty);
set => SetValue(PageIndexProperty, value);
}
#endregion PageIndex
#region MaxPageInterval
/// <summary>
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
/// </summary>
public static readonly DependencyProperty MaxPageIntervalProperty = DependencyProperty.Register(
"MaxPageInterval", typeof(int), typeof(Pagination), new PropertyMetadata(3, (o, args) =>
{
if (o is Pagination pagination)
{
pagination.Update();
}
}), value =>
{
var intValue = (int)value;
return intValue >= 0;
});
/// <summary>
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
/// </summary>
public int MaxPageInterval
{
get => (int)GetValue(MaxPageIntervalProperty);
set => SetValue(MaxPageIntervalProperty, value);
}
#endregion MaxPageInterval
#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;
_textBlockLeft = GetTemplateChild(ElementTextBlockLeft) as TextBlock;
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
_textBlockRight = GetTemplateChild(ElementTextBlockRight) as TextBlock;
_buttonLast = GetTemplateChild(ElementButtonLast) as RadioButton;
CheckNull();
_appliedTemplate = true;
Update();
}
#endregion Public Methods
#region Private Methods
private void CheckNull()
{
if (_buttonLeft == null || _buttonRight == null || _buttonFirst == null ||
_textBlockLeft == null || _panelMain == null || _textBlockRight == null ||
_buttonLast == null) throw new Exception();
}
/// <summary>
/// 更新
/// </summary>
private void Update()
{
if (!_appliedTemplate) return;
_buttonLeft.IsEnabled = PageIndex > 1;
_buttonRight.IsEnabled = PageIndex < MaxPageCount;
if (MaxPageInterval == 0)
{
_buttonFirst.Collapse();
_buttonLast.Collapse();
_textBlockLeft.Collapse();
_textBlockRight.Collapse();
_panelMain.Children.Clear();
var selectButton = CreateButton(PageIndex);
_panelMain.Children.Add(selectButton);
selectButton.IsChecked = true;
return;
}
_buttonFirst.Show();
_buttonLast.Show();
_textBlockLeft.Show();
_textBlockRight.Show();
//更新最后一页
if (MaxPageCount == 1)
{
_buttonLast.Collapse();
}
else
{
_buttonLast.Show();
_buttonLast.Tag = MaxPageCount.ToString();
}
//更新省略号
var right = MaxPageCount - PageIndex;
var left = PageIndex - 1;
_textBlockRight.Show(right > MaxPageInterval);
_textBlockLeft.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 (int i = 0; i < MaxPageInterval - 1; i++)
{
if (--sub > 1)
{
_panelMain.Children.Insert(0, CreateButton(sub));
}
else
{
break;
}
}
var add = PageIndex;
for (int 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 RadioButton
{
Style = ResourceHelper.GetResource<Style>(ResourceToken.PaginationButtonStyle),
Tag = page.ToString()
};
}
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
if (!(e.OriginalSource is RadioButton button)) return;
if (button.IsChecked == false) return;
PageIndex = int.Parse(button.Tag.ToString());
}
#endregion Private Methods
}
}