diff --git a/HandyControl/Controls/Pagination.xaml b/HandyControl/Controls/Pagination.xaml
new file mode 100644
index 00000000..a7cc89d4
--- /dev/null
+++ b/HandyControl/Controls/Pagination.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandyControl/Controls/Pagination.xaml.cs b/HandyControl/Controls/Pagination.xaml.cs
new file mode 100644
index 00000000..034defbb
--- /dev/null
+++ b/HandyControl/Controls/Pagination.xaml.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using HandyControl.Data;
+using HandyControl.Tools.Extension;
+
+namespace HandyControl.Controls
+{
+ ///
+ /// Pagination.xaml 的交互逻辑
+ ///
+ public partial class Pagination
+ {
+ ///
+ /// 页面更新事件
+ ///
+ public static readonly RoutedEvent PageUpdatedEvent =
+ EventManager.RegisterRoutedEvent("PageUpdated", RoutingStrategy.Bubble,
+ typeof(EventHandler>), typeof(Pagination));
+
+ public Pagination() => InitializeComponent();
+
+ ///
+ /// 最大页数
+ ///
+ 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;
+ }));
+
+ ///
+ /// 最大页数
+ ///
+ public int MaxPageCount
+ {
+ get => (int)GetValue(MaxPageCountProperty);
+ set => SetValue(MaxPageCountProperty, value);
+ }
+
+ ///
+ /// 每页的数据量
+ ///
+ public static readonly DependencyProperty DataCountPerPageProperty = DependencyProperty.Register(
+ "DataCountPerPage", typeof(int), typeof(Pagination), new PropertyMetadata(20, (o, args) =>
+ {
+ if (o is Pagination pagination && args.NewValue is int)
+ {
+ pagination.Update();
+ }
+ }, (o, value) =>
+ {
+ if (!(o is Pagination)) return 1;
+ var intValue = (int)value;
+ if (intValue < 1)
+ {
+ return 1;
+ }
+ return intValue;
+ }));
+
+ ///
+ /// 每页的数据量
+ ///
+ public int DataCountPerPage
+ {
+ get => (int)GetValue(DataCountPerPageProperty);
+ set => SetValue(DataCountPerPageProperty, value);
+ }
+
+ ///
+ /// 当前页
+ ///
+ 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(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;
+ }));
+
+ ///
+ /// 当前页
+ ///
+ public int PageIndex
+ {
+ get => (int)GetValue(PageIndexProperty);
+ set => SetValue(PageIndexProperty, value);
+ }
+
+ ///
+ /// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
+ ///
+ 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;
+ });
+
+ ///
+ /// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
+ ///
+ public int MaxPageInterval
+ {
+ get => (int)GetValue(MaxPageIntervalProperty);
+ set => SetValue(MaxPageIntervalProperty, value);
+ }
+
+ ///
+ /// 页面更新事件
+ ///
+ public event EventHandler> PageUpdated
+ {
+ add => AddHandler(PageUpdatedEvent, value);
+ remove => RemoveHandler(PageUpdatedEvent, value);
+ }
+
+ ///
+ /// 更新
+ ///
+ private void Update()
+ {
+ LeftButton.IsEnabled = PageIndex > 1;
+ RightButton.IsEnabled = PageIndex < MaxPageCount;
+ if (MaxPageInterval == 0)
+ {
+ FirstButton.Visibility = Visibility.Collapsed;
+ LastButton.Visibility = Visibility.Collapsed;
+ LeftTextBlock.Visibility = Visibility.Collapsed;
+ RightTextBlock.Visibility = Visibility.Collapsed;
+ MainPanel.Children.Clear();
+ var selectButton = CreateButton(PageIndex);
+ MainPanel.Children.Add(selectButton);
+ selectButton.IsChecked = true;
+ return;
+ }
+ FirstButton.Visibility = Visibility.Visible;
+ LastButton.Visibility = Visibility.Visible;
+ LeftTextBlock.Visibility = Visibility.Visible;
+ RightTextBlock.Visibility = Visibility.Visible;
+
+ //更新最后一页
+ if (MaxPageCount == 1)
+ {
+ LastButton.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ LastButton.Visibility = Visibility.Visible;
+ LastButton.Tag = MaxPageCount.ToString();
+ }
+
+ //更新省略号
+ var right = MaxPageCount - PageIndex;
+ var left = PageIndex - 1;
+ RightTextBlock.Visibility = right > MaxPageInterval ? Visibility.Visible : Visibility.Collapsed;
+ LeftTextBlock.Visibility = left > MaxPageInterval ? Visibility.Visible : Visibility.Collapsed;
+
+ //更新中间部分
+ MainPanel.Children.Clear();
+ if (PageIndex > 1 && PageIndex < MaxPageCount)
+ {
+ var selectButton = CreateButton(PageIndex);
+ MainPanel.Children.Add(selectButton);
+ selectButton.IsChecked = true;
+ }
+ else if (PageIndex == 1)
+ {
+ FirstButton.IsChecked = true;
+ }
+ else
+ {
+ LastButton.IsChecked = true;
+ }
+
+ var sub = PageIndex;
+ for (int i = 0; i < MaxPageInterval - 1; i++)
+ {
+ if (--sub > 1)
+ {
+ MainPanel.Children.Insert(0, CreateButton(sub));
+ }
+ else
+ {
+ break;
+ }
+ }
+ var add = PageIndex;
+ for (int i = 0; i < MaxPageInterval - 1; i++)
+ {
+ if (++add < MaxPageCount)
+ {
+ MainPanel.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 = FindResource("PaginationButtonStyle") as Style,
+ Tag = page.ToString()
+ };
+ }
+
+ private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
+ {
+ if (!(e.OriginalSource is RadioButton button)) return;
+ PageIndex = int.Parse(button.Tag.ToString());
+ }
+ }
+}
diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj
index bec70150..4cde2006 100644
--- a/HandyControl/HandyControl.csproj
+++ b/HandyControl/HandyControl.csproj
@@ -48,6 +48,9 @@
+
+ Pagination.xaml
+
@@ -121,6 +124,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -185,6 +192,10 @@
MSBuild:Compile
Designer
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -205,6 +216,14 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/HandyControl/Themes/Styles/Base/ScrollViewerBaseStyle.xaml b/HandyControl/Themes/Styles/Base/ScrollViewerBaseStyle.xaml
new file mode 100644
index 00000000..cdcdf2ee
--- /dev/null
+++ b/HandyControl/Themes/Styles/Base/ScrollViewerBaseStyle.xaml
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandyControl/Themes/Styles/Pagination.xaml b/HandyControl/Themes/Styles/Pagination.xaml
new file mode 100644
index 00000000..96243c0a
--- /dev/null
+++ b/HandyControl/Themes/Styles/Pagination.xaml
@@ -0,0 +1,51 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/HandyControl/Themes/Styles/ScrollViewer.xaml b/HandyControl/Themes/Styles/ScrollViewer.xaml
new file mode 100644
index 00000000..e1b66ce2
--- /dev/null
+++ b/HandyControl/Themes/Styles/ScrollViewer.xaml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandyControl/Themes/Styles/Style.xaml b/HandyControl/Themes/Styles/Style.xaml
index 46b6e18e..a5596eca 100644
--- a/HandyControl/Themes/Styles/Style.xaml
+++ b/HandyControl/Themes/Styles/Style.xaml
@@ -3,29 +3,32 @@
+
-
+
+
-
+
+
+
+
-
+
+
+
-
-
-
-
- -->
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandyControlDemo/MainWindow.xaml b/HandyControlDemo/MainWindow.xaml
index a15f8e15..290bd2ce 100644
--- a/HandyControlDemo/MainWindow.xaml
+++ b/HandyControlDemo/MainWindow.xaml
@@ -648,7 +648,7 @@
-->
-
+