# 所用到的关键知识点
① 自定义用户控件 (整个Page 是一个用自定义用户控件)
② 自定义控件 (每一个页面小按键是自定义控件)
③ 样式触发器 (Buttontype 改变时自动切换控件模板)
④ 自定义事件给引用者使用 (当点击每个页面按键时触发)
⑤ 依赖项属性 以及 属性改变回调事件
⑥ 其它
#开发和运行阶段的效果图片
1、开发时效果图
2、运行时的效果图
![](https://i-blog.csdnimg.cn/blog_migrate/32b2d96a1ca188ce664fe6bdd80f0227.gif)
# Paginater 的实现原码
public partial class Paginator : UserControl
{
#region variables
private const String PageTag = "page";
private const String FirstTag = "First";
private const String UpTag = "Up";
private const String NextTag = "Next";
private const String LastTag = "Last";
#endregion
#region DependencyProperty Register
public static readonly DependencyProperty SelectedForegroundProperty = DependencyProperty.Register("SelectedForground", typeof(Brush), typeof(TabButton), new PropertyMetadata(Brushes.Black, new PropertyChangedCallback(OnPropertyChanged)));
public static readonly DependencyProperty SelectedeBackgroundProperty = DependencyProperty.Register("SelectedeBackground", typeof(Brush), typeof(TabButton), new PropertyMetadata(Brushes.LightSlateGray, new PropertyChangedCallback(OnPropertyChanged)));
public static readonly DependencyProperty SelectedIndicatorColorProperty = DependencyProperty.Register("SelectedIndicatorColor", typeof(Brush), typeof(TabButton), new PropertyMetadata(Brushes.RoyalBlue, new PropertyChangedCallback(OnPropertyChanged)));
public static readonly DependencyProperty SelectedIndicatorHeightProperty = DependencyProperty.Register("SelectedIndicatorHeight", typeof(int), typeof(TabButton), new PropertyMetadata(1, new PropertyChangedCallback(OnPropertyChanged)));
public static readonly DependencyProperty ButtonTypeProperty = DependencyProperty.Register("ButtonType", typeof(PageButtonType), typeof(Paginator), new PropertyMetadata(PageButtonType.Radius, new PropertyChangedCallback(OnPropertyChanged)));
public static readonly DependencyProperty DataCountProperty = DependencyProperty.Register("DataCount", typeof(int), typeof(Paginator), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(OnDataCountChanged)));
public static readonly DependencyProperty ItemCountCountProperty = DependencyProperty.Register("ItemCount", typeof(int), typeof(Paginator), new PropertyMetadata(10, new PropertyChangedCallback(OnPaginatorCountChanged)));
public static readonly DependencyProperty CurrentPageProperty = DependencyProperty.Register("CurrentPage", typeof(int), typeof(Paginator), new PropertyMetadata(1, new PropertyChangedCallback(OnCurrentPageChanged)));
#endregion
/// <summary>
/// 选中时的前景颜色
/// </summary>
public Brush SelectedForground
{
get { return (Brush)GetValue(SelectedForegroundProperty); }
set { SetValue(SelectedForegroundProperty, value); }
}
public Brush SelectedBackground
{
get { return (Brush)GetValue(SelectedeBackgroundProperty); }
set { SetValue(SelectedeBackgroundProperty, value); }
}
public Brush SelectedIndicatorColor
{
get { return (Brush)GetValue(SelectedIndicatorColorProperty); }
set { SetValue(SelectedIndicatorColorProperty, value); }
}
public int SelectedIndicatorHeight
{
get { return (int)GetValue(SelectedIndicatorHeightProperty); }
set { SetValue(SelectedIndicatorHeightProperty, value); }
}
public int DataCount
{
get { return (int)GetValue(DataCountProperty); }
set { SetValue(DataCountProperty, value); }
}
public PageButtonType ButtonType
{
get { return (PageButtonType)GetValue(ButtonTypeProperty); }
set { SetValue(ButtonTypeProperty, value); }
}
private static void OnDataCountChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Paginator Paginator = sender as Paginator;
Paginator.Measure();
}
private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
Paginator p = sender as Paginator;
p.Measure();
}
public int ItemCount
{
get { return (int)GetValue(ItemCountCountProperty); }
set
{
if ((int)value <= 0)
{
value = 10;
}
SetValue(ItemCountCountProperty, value);
}
}
private static void OnPaginatorCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Paginator Paginator = d as Paginator;
Paginator.Measure();
}
public int CurrentPage
{
get { return (int)GetValue(CurrentPageProperty); }
set { SetValue(CurrentPageProperty, value); }
}
public int LastPage { get; set; }
#region export event
public static readonly RoutedEvent PaginatorSelectedEvent = EventManager.RegisterRoutedEvent("PaginatorSelected", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<int>), typeof(Paginator));
public event RoutedPropertyChangedEventHandler<int> PaginatorSelected
{
add { AddHandler(PaginatorSelectedEvent, value); }
remove { RemoveHandler(PaginatorSelectedEvent, value); }
}
private static void OnCurrentPageChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
Paginator Paginator = sender as Paginator;
int oldValue = (int)args.OldValue;
int newValue = (int)args.NewValue;
Paginator.Measure();
//引发事件
Paginator.RaiseEventPaginatorSelected(newValue, oldValue);
}
private void RaiseEventPaginatorSelected(int newValue, int oldValue)
{
RoutedPropertyChangedEventArgs<int> args = new RoutedPropertyChangedEventArgs<int>(newValue, oldValue)
{
RoutedEvent = PaginatorSelectedEvent
};
RaiseEvent(args);
}
#endregion
public Paginator()
{
InitializeComponent();
}
#region Measure
private void Measure()
{
if (DataCount <= 0 || ItemCount <= 0)
{
return;
}
int pages = DataCount / ItemCount;
if (DataCount % ItemCount > 0)
{
pages += 1;
}
LastPage = pages;
//处理不需要动态生成的页面按键
HandleStaticPageBtn();
int side = 2;
int windows = 6;
if (pages > 1)
{
this.PagePanel.Visibility = Visibility.Visible;
this.PagePanel.Children.Clear();
if (pages < (side * windows))
{
leftDot.Visibility = Visibility.Collapsed;
RightDot.Visibility = Visibility.Collapsed;
InsertPageBtn(1, pages);
}
else
{
if (CurrentPage == 1)
{
RadiusUpPage.Visibility = Visibility.Collapsed;
CircleUpPage.Visibility = Visibility.Collapsed;
UdLineUpPage.Visibility = Visibility.Collapsed;
}
if (CurrentPage - windows <= 1) {
leftDot.Visibility = Visibility.Collapsed;
RadiusFirstPage.Visibility = Visibility.Collapsed;
CircleFirstPage.Visibility = Visibility.Collapsed;
UdLineFirstPage.Visibility = Visibility.Collapsed;
}
if (CurrentPage == pages)
{
RadiusNextPage.Visibility = Visibility.Collapsed;
CircleNextPage.Visibility = Visibility.Collapsed;
UdLineNextPage.Visibility = Visibility.Collapsed;
}
if ((CurrentPage + windows) < pages)
{
RadiusLastPage.Visibility = Visibility.Collapsed;
CircleLastPage.Visibility = Visibility.Collapsed;
UdLineLastPage.Visibility = Visibility.Collapsed;
RightDot.Visibility = Visibility.Collapsed;
}
if ((CurrentPage - windows) > 1)
{
leftDot.Visibility = Visibility.Visible;
switch (ButtonType)
{
case PageButtonType.Radius:
RadiusFirstPage.Visibility = Visibility.Visible;
break;
case PageButtonType.Circle:
CircleFirstPage.Visibility = Visibility.Visible;
break;
case PageButtonType.UdLine:
UdLineFirstPage.Visibility = Visibility.Visible;
break;
}
}
else
{
leftDot.Visibility = Visibility.Collapsed;
switch (ButtonType)
{
case PageButtonType.Radius:
RadiusFirstPage.Visibility = Visibility.Collapsed;
break;
case PageButtonType.Circle:
CircleFirstPage.Visibility = Visibility.Collapsed;
break;
case PageButtonType.UdLine:
UdLineFirstPage.Visibility = Visibility.Collapsed;
break;
}
}
if ((CurrentPage + windows) >= pages)
{
RightDot.Visibility = Visibility.Collapsed;
switch (ButtonType)
{
case PageButtonType.Radius:
RadiusLastPage.Visibility = Visibility.Collapsed;
break;
case PageButtonType.Circle:
CircleLastPage.Visibility = Visibility.Collapsed;
break;
case PageButtonType.UdLine:
UdLineLastPage.Visibility = Visibility.Collapsed;
break;
}
}
else
{
RightDot.Visibility = Visibility.Visible;
switch (ButtonType)
{
case PageButtonType.Radius:
RadiusLastPage.Visibility = Visibility.Visible;
break;
case PageButtonType.Circle:
CircleLastPage.Visibility = Visibility.Visible;
break;
case PageButtonType.UdLine:
UdLineLastPage.Visibility = Visibility.Visible;
break;
}
}
if (CurrentPage <= windows)
{
int end = CurrentPage + windows + (windows - CurrentPage);
InsertPageBtn(1, end);
if (end < pages)
{
RightDot.Visibility = Visibility.Visible;
}
else
{
RightDot.Visibility = Visibility.Collapsed;
}
}
else if (CurrentPage > windows)
{
int start = CurrentPage - windows;
if (start > 1)
{
leftDot.Visibility = Visibility.Visible;
}
else
{
leftDot.Visibility = Visibility.Collapsed;
}
int end = CurrentPage + windows;
if (end < pages)
{
RightDot.Visibility = Visibility.Visible;
}
else
{
end = end - (end - pages);
RightDot.Visibility = Visibility.Collapsed;
}
InsertPageBtn(start, end);
}
}
}
else
{
this.PagePanel.Visibility = Visibility.Collapsed;
leftDot.Visibility = Visibility.Collapsed;
RightDot.Visibility = Visibility.Collapsed;
}
}
private void InsertPageBtn(int startPage, int endPage)
{
for (int i = startPage; i <= endPage; i++)
{
if (i == CurrentPage)
{
this.PagePanel.Children.Add(CreateBtn(i, true));
}
else
{
this.PagePanel.Children.Add(CreateBtn(i));
}
}
}
#endregion
/// <summary>
/// 处理不需要动态生成的页面按键
/// </summary>
private void HandleStaticPageBtn()
{
if (LastPage <= 1)
{
RadiusFirstPage.Visibility = Visibility.Collapsed;
RadiusUpPage.Visibility = Visibility.Collapsed;
RadiusNextPage.Visibility = Visibility.Collapsed;
RadiusLastPage.Visibility = Visibility.Collapsed;
CircleFirstPage.Visibility = Visibility.Collapsed;
CircleNextPage.Visibility = Visibility.Collapsed;
CircleUpPage.Visibility = Visibility.Collapsed;
CircleLastPage.Visibility = Visibility.Collapsed;
UdLineFirstPage.Visibility = Visibility.Collapsed;
UdLineUpPage.Visibility = Visibility.Collapsed;
UdLineNextPage.Visibility = Visibility.Collapsed;
UdLineLastPage.Visibility = Visibility.Collapsed;
return;
}
switch (ButtonType)
{
case PageButtonType.UdLine:
RadiusFirstPage.Visibility = Visibility.Collapsed;
RadiusUpPage.Visibility = Visibility.Collapsed;
RadiusNextPage.Visibility = Visibility.Collapsed;
RadiusLastPage.Visibility = Visibility.Collapsed;
CircleFirstPage.Visibility = Visibility.Collapsed;
CircleNextPage.Visibility = Visibility.Collapsed;
CircleUpPage.Visibility = Visibility.Collapsed;
CircleLastPage.Visibility = Visibility.Collapsed;
UdLineFirstPage.Visibility = Visibility.Visible;
UdLineUpPage.Visibility = Visibility.Visible;
UdLineNextPage.Visibility = Visibility.Visible;
UdLineLastPage.Visibility = Visibility.Visible;
break;
case PageButtonType.Circle:
RadiusFirstPage.Visibility = Visibility.Collapsed;
RadiusUpPage.Visibility = Visibility.Collapsed;
RadiusNextPage.Visibility = Visibility.Collapsed;
RadiusLastPage.Visibility = Visibility.Collapsed;
CircleFirstPage.Visibility = Visibility.Visible;
CircleNextPage.Visibility = Visibility.Visible;
CircleUpPage.Visibility = Visibility.Visible;
CircleLastPage.Visibility = Visibility.Visible;
UdLineFirstPage.Visibility = Visibility.Collapsed;
UdLineUpPage.Visibility = Visibility.Collapsed;
UdLineNextPage.Visibility = Visibility.Collapsed;
UdLineLastPage.Visibility = Visibility.Collapsed;
break;
case PageButtonType.Radius:
RadiusFirstPage.Visibility = Visibility.Visible;
RadiusUpPage.Visibility = Visibility.Visible;
RadiusNextPage.Visibility = Visibility.Visible;
RadiusLastPage.Visibility = Visibility.Visible;
CircleFirstPage.Visibility = Visibility.Collapsed;
CircleNextPage.Visibility = Visibility.Collapsed;
CircleUpPage.Visibility = Visibility.Collapsed;
CircleLastPage.Visibility = Visibility.Collapsed;
UdLineFirstPage.Visibility = Visibility.Collapsed;
UdLineUpPage.Visibility = Visibility.Collapsed;
UdLineNextPage.Visibility = Visibility.Collapsed;
UdLineLastPage.Visibility = Visibility.Collapsed;
break;
default:
RadiusFirstPage.Visibility = Visibility.Visible;
RadiusUpPage.Visibility = Visibility.Visible;
RadiusNextPage.Visibility = Visibility.Visible;
RadiusLastPage.Visibility = Visibility.Visible;
CircleFirstPage.Visibility = Visibility.Collapsed;
CircleNextPage.Visibility = Visibility.Collapsed;
CircleUpPage.Visibility = Visibility.Collapsed;
CircleLastPage.Visibility = Visibility.Collapsed;
UdLineFirstPage.Visibility = Visibility.Collapsed;
UdLineUpPage.Visibility = Visibility.Collapsed;
UdLineNextPage.Visibility = Visibility.Collapsed;
UdLineLastPage.Visibility = Visibility.Collapsed;
break;
}
}
private PageButton CreateBtn(int PaginatorIndex, Boolean isCurrent = false)
{
PageButton button = new PageButton();
button.Content = PaginatorIndex.ToString();
button.Type = (int)ButtonType;
button.FontSize = this.FontSize;
button.IsChecked = isCurrent;
button.IndicatorHeight = SelectedIndicatorHeight;
button.Tag = PageTag;
button.ActiveForground = SelectedForground;
button.ActiveIndicatorColor = this.SelectedIndicatorColor;
button.ActiveBackground = this.SelectedBackground;
button.Background = this.Background;
button.Click += PageButton_Click;
return button;
}
private void PageButton_Click(object sender, RoutedEventArgs e)
{
PageButton button = sender as PageButton;
String tag = button.Tag.ToString();
int index = 0;
try
{
index = Convert.ToInt32(button.Content);
CurrentPage = index;
}
catch
{
// static orther btn
button.IsChecked = false;
switch (tag)
{
case FirstTag:
CurrentPage = 1;
break;
case UpTag:
CurrentPage -= 1;
break;
case NextTag:
CurrentPage += 1;
break;
case LastTag:
CurrentPage = LastPage;
break;
default:
break;
}
}
Console.WriteLine("==== :" + tag + " page:" + index);
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Measure();
}
}
#、XAML
<UserControl x:Class="MyCustomControlLibrary.Paginator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyCustomControlLibrary"
mc:Ignorable="d" Background="White"
Loaded="UserControl_Loaded"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Orientation="Horizontal" x:Name="PageContine" VerticalAlignment="Center">
<local:PageButton x:Name="RadiusFirstPage" Tag="First" Width="50" Content="首页" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="CircleFirstPage" Tag="First" Content="首" Type="1" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="UdLineFirstPage" Tag="First" Content="首" Type="0" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="{StaticResource myBlue}" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="RadiusUpPage" Tag="Up" Width="50" Content="上一页" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="CircleUpPage" Tag="Up" Content="上" Type="1" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="UdLineUpPage" Tag="Up" Content="上" Type="0" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="{StaticResource myBlue}" Padding="1" Click="PageButton_Click"/>
<TextBlock x:Name="leftDot" Text="……" FontSize="14" VerticalAlignment="Bottom" Margin="2" Visibility="Collapsed"/>
<WrapPanel x:Name="PagePanel" Visibility="Visible">
<local:PageButton Content="1" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" IsChecked="True" Click="PageButton_Click"/>
<local:PageButton Content="2" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton Content="3" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton Content="4" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton Content="5" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton Content="6" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton Content="7" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
</WrapPanel>
<TextBlock x:Name="RightDot" Text="……" FontSize="14" VerticalAlignment="Bottom" Margin="2" Visibility="Collapsed"/>
<local:PageButton x:Name="RadiusNextPage" Tag="Next" Content="下一页" Width="50" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="CircleNextPage" Tag="Next" Content="下" Type="1" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="UdLineNextPage" Tag="Next" Content="下" Type="0" Margin="2" ActiveIndicatorColor="{StaticResource myBlue}" ActiveBackground="{StaticResource myBlue}" ActiveForground="{StaticResource myBlue}" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="RadiusLastPage" Tag="Last" Width="50" Content="尾页" Type="2" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="CircleLastPage" Tag="Last" Content="尾" Type="2" Margin="1" ActiveBackground="{StaticResource myBlue}" ActiveForground="White" Padding="1" Click="PageButton_Click"/>
<local:PageButton x:Name="UdLineLastPage" Tag="Last" Content="尾" Type="0" Margin="2" ActiveBackground="{StaticResource myBlue}" ActiveForground="{StaticResource myBlue}" Padding="1" Click="PageButton_Click"/>
</StackPanel>
</Grid>
</UserControl>
5、 后端代码有点乱 ,是因为XAML 默认就显示些控件 如上一面 首页 这些不需要动态生成的,主要为了性能的考虑 。
如果这些控件也动态生成,可能后端代码会少很多。
好久没有好好的搞代码拉,花了整整两天的时间。不足之处欢迎指出,也希望能帮到一些朋面。