最近作一個演示的管理系統項目,須要用到分頁控件,在網上找了不少,依然找到與UI模版匹配的,最後乾脆本身寫一個。express
分頁控件分析:app
一、分頁控件分簡單顯示和複雜顯示兩種;ide
二、包含上一頁、下一頁以及頁碼明細邏輯處理;this
三、頁碼總數小於7時顯示默認顯示,大於7時切換複雜顯示;spa
四、頁碼數、索引、總條數計算等;code
先來一張效果圖: component
啥也不說了直接上代碼orm
MISPager.xaml部分xml
<ResourceDictionary 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:mis="clr-namespace:MIS.ClientUI.Controls" mc:Ignorable="d" > <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MIS.ClientUI;component/Themes/Corlors.xaml" /> <ResourceDictionary Source="pack://application:,,,/MIS.ClientUI;component/Themes/Share.xaml" /> </ResourceDictionary.MergedDictionaries> <!--系統默認的分頁控件--> <Style x:Key="MISDefaultDataPagerStyle" TargetType="{x:Type mis:MISPager}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type mis:MISPager}"> <Grid Margin="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <StackPanel Margin="0" Orientation="Horizontal"> <TextBlock TextWrapping="Wrap" Text="共" Margin="0" VerticalAlignment="Center"/> <TextBlock x:Name="PART_Count" HorizontalAlignment="Stretch" TextWrapping="Wrap" VerticalAlignment="Center" Text="1256" Foreground="#FF056DAE"/> <TextBlock TextWrapping="Wrap" Text="條記錄,當前顯示第" Margin="0" VerticalAlignment="Center"/> <TextBlock x:Name="PART_PageIndex" TextWrapping="Wrap" Text=" 2 " Margin="0" VerticalAlignment="Center" Foreground="#FF056DAE"/> <TextBlock TextWrapping="Wrap" Text="頁" Margin="0" VerticalAlignment="Center"/> </StackPanel> <Border BorderBrush="Black" Grid.Column="1" Margin="0" HorizontalAlignment="Right"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="40"/> </Grid.ColumnDefinitions> <Border BorderBrush="#FFDDDDDD" BorderThickness="1,1,0,1" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto" CornerRadius="2,0,0,2"> <mis:MISImageButton BorderThickness="0" MISCornerRadius="0" GeometryIcon="{DynamicResource DefaultDataPagerPreviouspage}" Style="{DynamicResource DefaultISvgImageButtonStyle}" x:Name="PART_Previouspage" /> </Border> <Border Grid.ColumnSpan="1" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto" Grid.Column="1" BorderBrush="#FFDDDDDD" BorderThickness="0,1"> <StackPanel x:Name="PART_Content" Orientation="Horizontal"> </StackPanel> </Border> <Border BorderBrush="#FFDDDDDD" BorderThickness="1" Margin="0" Grid.Column="2" CornerRadius="0,2,2,0"> <mis:MISImageButton BorderThickness="0" MISCornerRadius="0" GeometryIcon="{DynamicResource DefaultDataPagerNextpage}" x:Name="PART_Nextpage" Style="{DynamicResource DefaultISvgImageButtonStyle}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"/> </Border> </Grid> </Border> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
MISPager.cs部分blog
1 namespace MIS.ClientUI.Controls 2 { 3 /// <summary> 4 /// 分頁控件 5 /// </summary> 6 [TemplatePart(Name = MISPager.MIS_PART_CONTENT, Type = typeof(StackPanel))] 7 [TemplatePart(Name = MISPager.MIS_PART_PREVIOUSPAGE, Type = typeof(MISImageButton))] 8 [TemplatePart(Name = MISPager.MIS_PART_NEXTPAGE, Type = typeof(MISImageButton))] 9 [TemplatePart(Name = MISPager.MIS_PART_COUNT, Type = typeof(TextBlock))] 10 [TemplatePart(Name = MISPager.MIS_PART_PAGEINDEX, Type = typeof(TextBlock))] 11 public partial class MISPager : Control 12 { 13 private const String MIS_PART_CONTENT = "PART_Content"; 14 private const String MIS_PART_PREVIOUSPAGE = "PART_Previouspage"; 15 private const String MIS_PART_NEXTPAGE = "PART_Nextpage"; 16 private const String MIS_PART_COUNT = "PART_Count"; 17 private const String MIS_PART_PAGEINDEX = "PART_PageIndex"; 18 19 private MISImageButton PART_Nextpage; //下一頁事件 20 private MISImageButton PART_Previouspage; //上一頁事件 21 private StackPanel PART_Content; //子頁碼 22 private TextBlock PART_Count; 23 private TextBlock PART_PageIndex; 24 25 private PagerType mPagerType = PagerType.Default; //當前分頁控件類型,複雜、默認 26 private List<Int32> mCurrentPagers = new List<Int32>(); //當前分頁控件顯示的頁碼索引 27 private Boolean mCurrentIsAddEllipsisCtrl = false; //當前是否已添加省略號控件(當前仍是能夠直接在集合控件中比對) 28 29 public MISPager() 30 { 31 32 } 33 34 //初始化控件時調用的系統方法 35 public override void OnApplyTemplate() 36 { 37 base.OnApplyTemplate(); 38 this.PART_Content = this.GetTemplateChild(MISPager.MIS_PART_CONTENT) as StackPanel; 39 this.PART_Nextpage = this.GetTemplateChild(MISPager.MIS_PART_NEXTPAGE) as MISImageButton; 40 this.PART_Previouspage = this.GetTemplateChild(MISPager.MIS_PART_PREVIOUSPAGE) as MISImageButton; 41 this.PART_Count = this.GetTemplateChild(MISPager.MIS_PART_COUNT) as TextBlock; 42 this.PART_PageIndex = this.GetTemplateChild(MISPager.MIS_PART_PAGEINDEX) as TextBlock; 43 //計算頁碼數 44 this.PageCount = (Int32)Math.Ceiling((Double)this.Total / (Double)this.PageSize); 45 this.PART_Count.Text = this.Total.ToString(); 46 //當總頁碼小於7頁,顯示一、二、三、四、五、六、7 47 if (this.PageCount <= 7) 48 { 49 this.mPagerType = PagerType.Default; 50 for (int i = 0; i < this.PageCount; i++) 51 { 52 var misImgBtn = new MISLinkButton() 53 { 54 Content = (i + 1).ToString(), 55 Width = 35, 56 BorderThickness = new Thickness(1, 0, 0, 0), 57 Style = Application.Current.FindResource("DefaultLinkButton2Style") as Style 58 }; 59 this.mCurrentPagers.Add((i + 1)); 60 misImgBtn.Click += OnMisImgBtn_Click; 61 if (this.PART_Content != null) 62 { 63 this.PART_Content.Children.Add(misImgBtn); 64 } 65 } 66 } 67 else 68 { 69 this.mPagerType = PagerType.Complex; 70 for (int i = 0; i < 5; i++) 71 { 72 var misImgBtn = new MISLinkButton() { Content = (i + 1).ToString(), Width = 35, BorderThickness = new Thickness(1, 0, 0, 0), Style = Application.Current.FindResource("DefaultLinkButton2Style") as Style }; 73 misImgBtn.Click += OnMisImgBtn_Click; 74 if (i.Equals(0)) misImgBtn.Tag = 0; //設置左控制點 75 if (i.Equals(4)) misImgBtn.Tag = 5; //設置右控制點 76 this.mCurrentPagers.Add((i + 1)); 77 if (this.PART_Content != null) 78 { 79 this.PART_Content.Children.Add(misImgBtn); 80 } 81 } 82 this.PART_Content.Children.Add(new MISLinkButton() { Content = "...", Width = 35, BorderThickness = new Thickness(1, 0, 0, 0), Style = Application.Current.FindResource("DefaultLinkButton3Style") as Style }); 83 this.PART_Content.Children.Add(new MISLinkButton() { Content = this.PageCount.ToString(), Width = 35, BorderThickness = new Thickness(1, 0, 0, 0), Style = Application.Current.FindResource("DefaultLinkButton2Style") as Style }); 84 } 85 this.SetLinkButtonFocus(0); 86 this._SetNextpageAndPreviouspageState(); 87 if (this.PART_Previouspage != null) 88 { 89 this.PART_Previouspage.Click += OnPART_Previouspage_Click; 90 } 91 if (this.PART_Nextpage != null) 92 { 93 this.PART_Nextpage.Click += OnPART_Nextpage_Click; 94 } 95 } 96 97 #region 依賴屬性 98 99 #region 當前DataGrid顯示的數據總條數,用於計算頁碼數 100 /// <summary> 101 /// 當前DataGrid顯示的數據總條數,用於計算頁碼數 102 /// </summary> 103 public Int32 Total 104 { 105 get { return (Int32)GetValue(TotalProperty); } 106 set { SetValue(TotalProperty, value); } 107 } 108 109 public static readonly DependencyProperty TotalProperty = 110 DependencyProperty.Register("Total", typeof(Int32), typeof(MISPager), new PropertyMetadata(0)); 111 112 #endregion 113 114 #region 當前DataGrid每頁顯示條數,用於計算頁碼數 115 /// <summary> 116 /// 每頁顯示條數 117 /// </summary> 118 public Int32 PageSize 119 { 120 get { return (Int32)GetValue(PageSizeProperty); } 121 set { SetValue(PageSizeProperty, value); } 122 } 123 124 public static readonly DependencyProperty PageSizeProperty = 125 DependencyProperty.Register("PageSize", typeof(Int32), typeof(MISPager), new PropertyMetadata(10)); 126 127 128 #endregion 129 130 #region 當前DataGrid當前頁碼索引 131 132 /// <summary> 133 /// 頁碼索引 134 /// </summary> 135 public Int32 PageIndex 136 { 137 get { return (Int32)GetValue(PageIndexProperty); } 138 set { SetValue(PageIndexProperty, value); } 139 } 140 141 public static readonly DependencyProperty PageIndexProperty = 142 DependencyProperty.Register("PageIndex", typeof(Int32), typeof(MISPager), new FrameworkPropertyMetadata(1)); 143 144 145 #endregion 146 147 #region 當前DataGrid總頁數 148 /// <summary> 149 /// 頁碼數 150 /// </summary> 151 public Int32 PageCount 152 { 153 get { return (Int32)GetValue(PageCountProperty); } 154 set { SetValue(PageCountProperty, value); } 155 } 156 157 public static readonly DependencyProperty PageCountProperty = 158 DependencyProperty.Register("PageCount", typeof(Int32), typeof(MISPager), new PropertyMetadata(0)); 159 160 #endregion 161 162 #endregion 163 164 #region 路由事件 165 166 //註冊分頁路由事件 167 public static readonly RoutedEvent PageChangedEvent = EventManager.RegisterRoutedEvent("PageChanged", 168 RoutingStrategy.Bubble, typeof(EventHandler<PageChangedEventArgs>), typeof(MISPager)); 169 170 171 public event EventHandler<PageChangedEventArgs> PageChanged 172 { 173 add 174 { 175 this.AddHandler(PageChangedEvent, value); 176 } 177 remove 178 { 179 this.RemoveHandler(PageChangedEvent, value); 180 } 181 } 182 183 184 #endregion 185 186 #region 私有方法 187 188 /// <summary> 189 /// 計算當前選中的分頁按鈕的索引 190 /// </summary> 191 private Int32 CalculationCurrentSelectPagerButtonWithIndex() 192 { 193 //當前控件顯示的頁碼集合 194 return this.mCurrentPagers.FindIndex((o) => { return o == this.PageIndex; }); 195 } 196 /// <summary> 197 /// 維護當前分頁控件顯示的頁碼數據 198 /// </summary> 199 /// <param name="addSubtract"></param> 200 private void _MaintainCurrentPagers(AddSubtract addSubtract) 201 { 202 if (addSubtract == AddSubtract.Add) 203 { 204 for (int i = 0; i < this.mCurrentPagers.Count; i++) 205 { 206 this.mCurrentPagers[i] = this.mCurrentPagers[i] + 1; 207 } 208 } 209 if (addSubtract == AddSubtract.subtract) 210 { 211 for (int i = 0; i < this.mCurrentPagers.Count; i++) 212 { 213 this.mCurrentPagers[i] = this.mCurrentPagers[i] - 1; 214 } 215 } 216 217 } 218 /// <summary> 219 /// 下一頁 220 /// </summary> 221 private void OnPART_Nextpage_Click(object sender, RoutedEventArgs e) 222 { 223 var _index = this.CalculationCurrentSelectPagerButtonWithIndex() + 1; 224 this.PageIndex++; 225 this._SetNextpageAndPreviouspageState(); 226 if (this.mPagerType == PagerType.Complex) //複雜分頁有效 227 { 228 // _index == 4 時爲右側控制點 229 if (_index == 4) 230 { 231 if (this.PageIndex == this.PageCount - 1) 232 { 233 this.PART_Nextpage.IsEnabled = false; //設置下一頁不可用 234 } 235 //檢測當前是否已添加省略號控件 236 if (!this.mCurrentIsAddEllipsisCtrl) 237 { 238 this.mCurrentIsAddEllipsisCtrl = true; 239 //在翻頁控件第一個位置添加一個省略號控件 240 this.PART_Content.Children.Insert(0, new MISLinkButton() { Content = "...", Width = 35, BorderThickness = new Thickness(1, 0, 0, 0), Style = Application.Current.FindResource("DefaultLinkButton3Style") as Style }); 241 } 242 //刷新UI(全部的分頁控件加1) 243 this._RefreshPager(AddSubtract.Add); 244 this._MaintainCurrentPagers(AddSubtract.Add); 245 } 246 else 247 { 248 this.SetLinkButtonFocus(_index); 249 } 250 } 251 else 252 { 253 //if (this.PageIndex == this.PageCount ) return; 254 this.SetLinkButtonFocus(_index); 255 } 256 257 } 258 /// <summary> 259 /// 上一頁 260 /// </summary> 261 private void OnPART_Previouspage_Click(object sender, RoutedEventArgs e) 262 { 263 //當前PageIndex在界面上顯示的索引,用於判斷控制點 264 var _index = this.CalculationCurrentSelectPagerButtonWithIndex() - 1; 265 this.PageIndex--; 266 this._SetNextpageAndPreviouspageState(); 267 if (this.mPagerType == PagerType.Complex) //複雜分頁有效 268 { 269 if (this.PageIndex == 1) 270 { 271 if (this.mCurrentIsAddEllipsisCtrl) 272 { 273 this.mCurrentIsAddEllipsisCtrl = false; 274 this.PART_Content.Children.RemoveAt(0); 275 this.SetLinkButtonFocus(0); 276 } 277 return; 278 } 279 if (_index == 0) //當前位置在左控制點時 280 { 281 //刷新UI(全部的分頁控件減1) 282 this._RefreshPager(AddSubtract.subtract); 283 this._MaintainCurrentPagers(AddSubtract.subtract); 284 } 285 else 286 { 287 this.SetLinkButtonFocus(_index); 288 } 289 } 290 else 291 { 292 //if (this.PageIndex == 1) return; 293 this.SetLinkButtonFocus(_index); 294 } 295 } 296 297 private void SetLinkButtonFocus(Int32 index) 298 { 299 if (this.mCurrentIsAddEllipsisCtrl) //包含省略號控件 300 { 301 this.PART_Content.Children[index + 1].Focus(); 302 } 303 else 304 { 305 this.PART_Content.Children[index].Focus(); 306 } 307 } 308 309 protected virtual void OnPageChanged() 310 { 311 var eventArgs = new PageChangedEventArgs(this.PageIndex) { RoutedEvent = PageChangedEvent, Source = this }; 312 this.RaiseEvent(eventArgs); 313 } 314 315 private void _RefreshPager(AddSubtract addSubtract) 316 { 317 /* 318 * 一、默認分頁的按鈕爲7個 319 * 二、當分頁總數小於等於7時,直接顯示1-7個分頁按鈕 320 * 三、當分頁總數大於7時,顯示當時爲一、二、三、四、五、...、999(999爲總頁數) 321 * 四、 322 * **/ 323 if (this.PART_Content.Children.Count > 0) 324 { 325 int _index = 0; // 326 int _contentCount = this.PART_Content.Children.Count; 327 if (this.mCurrentIsAddEllipsisCtrl) //當前包含前綴省略號控件 328 { 329 _index = 1; 330 _contentCount = _contentCount - 1; 331 } 332 for (int i = 0; i < _contentCount - 2; i++) 333 { 334 var misLinkBtn = this.PART_Content.Children[_index] as MISLinkButton; 335 if (misLinkBtn != null) 336 { 337 misLinkBtn.Content = addSubtract == AddSubtract.Add ? (Convert.ToInt32(misLinkBtn.Content) + 1).ToString() : (Convert.ToInt32(misLinkBtn.Content) - 1).ToString(); 338 } 339 _index++; 340 } 341 if (addSubtract == AddSubtract.Add) 342 { 343 //設置倒數第一個按鈕會選中狀態 344 this.PART_Content.Children[_index - 2].Focus(); 345 } 346 else 347 { //設置第二個按鈕會選中狀態 348 if (this.mCurrentIsAddEllipsisCtrl) 349 { 350 this.PART_Content.Children[2].Focus(); 351 } 352 else 353 { 354 this.PART_Content.Children[1].Focus(); 355 } 356 } 357 } 358 359 360 361 362 363 364 365 } 366 367 /// <summary> 368 /// 設置上一頁下一頁按鈕顯示狀態 369 /// </summary> 370 private void _SetNextpageAndPreviouspageState() 371 { 372 if (this.PageIndex == 1) 373 { 374 this.PART_Previouspage.IsEnabled = false; 375 } 376 if (this.PageIndex > 1) 377 { 378 this.PART_Previouspage.IsEnabled = true; 379 this.PART_Nextpage.IsEnabled = true; 380 } 381 if (this.mPagerType == PagerType.Complex) 382 { 383 if (this.PageIndex == this.PageCount - 1) 384 { 385 this.PART_Previouspage.IsEnabled = true; 386 this.PART_Nextpage.IsEnabled = false; 387 } 388 } 389 else 390 { 391 if (this.PageIndex == this.PageCount) 392 { 393 this.PART_Previouspage.IsEnabled = true; 394 this.PART_Nextpage.IsEnabled = false; 395 } 396 } 397 this.PART_PageIndex.Text = this.PageIndex.ToString(); 398 } 399 /// <summary> 400 /// 頁碼索引點擊事件 401 /// </summary> 402 /// <param name="sender"></param> 403 /// <param name="e"></param> 404 private void OnMisImgBtn_Click(object sender, RoutedEventArgs e) 405 { 406 //獲取當前點擊的PageIndex 407 var misImgBtn = sender as MISLinkButton; 408 this.PageIndex = Convert.ToInt32(misImgBtn.Content); 409 this._SetNextpageAndPreviouspageState(); 410 //當爲複雜控件時處理 411 if (this.mPagerType == PagerType.Complex) 412 { 413 this._RefreshPager(misImgBtn); 414 } 415 //執行路由回調 416 OnPageChanged(); 417 } 418 419 private void _RefreshPager(MISLinkButton misImgBtn) 420 { 421 //對比點擊的控件 422 if (misImgBtn.Tag != null) 423 { 424 if (misImgBtn.Tag.Equals(0)) 425 { 426 if (this.PageIndex > 1) 427 { 428 if (this.PageIndex == 2 && this.mCurrentIsAddEllipsisCtrl) //當前點擊第二頁時,顯示第一個並移除左側的省略號控件 429 { 430 this.mCurrentIsAddEllipsisCtrl = false; 431 this.PART_Content.Children.RemoveAt(0); 432 } 433 //刷新UI(全部的分頁控件減1) 434 this._RefreshPager(AddSubtract.subtract); 435 this._MaintainCurrentPagers(AddSubtract.subtract); 436 } 437 } 438 if (misImgBtn.Tag.Equals(5)) 439 { 440 //檢測當前是否已添加省略號控件 441 if (!this.mCurrentIsAddEllipsisCtrl) 442 { 443 this.mCurrentIsAddEllipsisCtrl = true; 444 //在翻頁控件第一個位置添加一個省略號控件 445 this.PART_Content.Children.Insert(0, new MISLinkButton() { Content = "...", Width = 35, BorderThickness = new Thickness(1, 0, 0, 0), Style = Application.Current.FindResource("DefaultLinkButton3Style") as Style }); 446 } 447 //刷新UI(全部的分頁控件加1) 448 this._RefreshPager(AddSubtract.Add); 449 this._MaintainCurrentPagers(AddSubtract.Add); 450 } 451 } 452 #endregion 453 } 454 } 455 456 /// <summary> 457 /// 分頁事件參數 458 /// </summary> 459 public class PageChangedEventArgs : RoutedEventArgs 460 { 461 462 public int PageIndex 463 { 464 get; 465 set; 466 } 467 468 public PageChangedEventArgs(int pageIndex) 469 : base() 470 { 471 PageIndex = pageIndex; 472 } 473 } 474 475 /// <summary> 476 /// 分頁控件類型 477 /// </summary> 478 public enum PagerType 479 { 480 /// <summary> 481 /// 默認 482 /// </summary> 483 Default, 484 /// <summary> 485 /// 複雜 486 /// </summary> 487 Complex 488 } 489 490 public enum AddSubtract 491 { 492 Add, subtract 493 } 494 }