天天看點

WPF 漂亮的自定義分頁控件

# 所用到的關鍵知識點

① 自定義使用者控件 (整個Page 是一個用自定義使用者控件)

② 自定義控件    (每一個頁面小按鍵是自定義控件)

③ 樣式觸發器  (Buttontype 改變時自動切換控件模闆)

④ 自定義事件給引用者使用 (當點選每個頁面按鍵時觸發)

⑤ 依賴項屬性 以及 屬性改變回調事件

⑥ 其它

#開發和運作階段的效果圖檔

1、開發時效果圖

WPF 漂亮的自定義分頁控件

2、運作時的效果圖

WPF 漂亮的自定義分頁控件

運作時效果

#  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 預設就顯示些控件 如上一面 首頁 這些不需要動态生成的,主要為了性能的考慮 。

      如果這些控件也動态生成,可能後端代碼會少很多。

好久沒有好好的搞代碼拉,花了整整兩天的時間。不足之處歡迎指出,也希望能幫到一些朋面。

繼續閱讀