最近在項目中遇到遠程加載數據的問題,由於服務器采用分頁方式返回數據,因此客戶端也相應的制作了一個分頁控件.代碼相對簡單,算做入門級的源碼.
效果如圖:

初步分析,分頁功能只需要3個核心變量:PageIndex,PageSize,TotalCount,2個事件:PageChanging,PageChanged,1個方法InitData.
PageIndex:記錄當前所在頁
PageSize:記錄每頁顯示的條目數
TotalCount:條目總數
由TotalCount和PageSize可以得到PageCount
PageChanging事件作為分頁的預處理事件,修改事件參數PageChangingEventArgs的IsCancel屬性可以取消分頁,這個是參考其他分頁控件的屬性
PageChanged事件是分頁后的處理事件,應用程序可以在此時獲取PageIndex進行操作.
InitData方法在數據加載時調用(主要是TotalCount屬性),用於初始化上面提到的核心變量.
WPF提供了很強大和實用的Binding功能,在開發控件時,應該盡量把屬性設計成依賴屬性.因此我把PageIndex,PageSize,TotalCount屬性全部設計成依賴屬性,並注冊了部分回調方法.這樣也可以很方便的實現控件和ViewModel的綁定.
核心代碼如下:
///
/// DataPager.xaml 的交互邏輯
///
public partial class DataPager : UserControl, INotifyPropertyChanged
{
public DataPager()
{
InitializeComponent();
}
///
/// 分頁前處理的事件,如果設置e.IsCancel=True將取消分頁
///
public event PageChangingRouteEventHandler PageChanging;
///
/// 分頁后處理的事件
///
public event PageChangedRouteEventHandler PageChanged;
#region 依賴屬性
///
/// 當前頁
///
public int PageIndex
{
get { return (int)GetValue(PageIndexProperty); }
set { SetValue(PageIndexProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentPage. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PageIndexProperty =
DependencyProperty.Register("PageIndex", typeof(int), typeof(DataPager), new UIPropertyMetadata(1, (sender, e) =>
{
var dp = sender as DataPager;
dp.ChangeNavigationButtonState();
}));
///
/// 每頁顯示數據大小
///
public int PageSize
{
get { return (int)GetValue(PageSizeProperty); }
set { SetValue(PageSizeProperty, value); InitData(); }
}
// Using a DependencyProperty as the backing store for PageSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PageSizeProperty =
DependencyProperty.Register("PageSize", typeof(int), typeof(DataPager), new UIPropertyMetadata(20, (sender, e) =>
{
var dp = sender as DataPager;
if (dp == null) return;
dp.ChangeNavigationButtonState();
}));
///
/// 記錄數量
///
public int TotalCount
{
get { return (int)GetValue(TotalCountProperty); }
set
{
SetValue(TotalCountProperty, value);
}
}
// Using a DependencyProperty as the backing store for TotalCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TotalCountProperty =
DependencyProperty.Register("TotalCount", typeof(int), typeof(DataPager), new UIPropertyMetadata(0, (sender, e) =>
{
var dp = sender as DataPager;
if (dp == null) return;
dp.InitData();
dp.ChangeNavigationButtonState();
}));
///
/// 總頁數
///
public int PageCount
{
get { return (int)GetValue(PageCountProperty); }
private set { SetValue(PageCountProperty, value); }
}
// Using a DependencyProperty as the backing store for PageCount. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PageCountProperty =
DependencyProperty.Register("PageCount", typeof(int), typeof(DataPager), new UIPropertyMetadata(1));
///
/// 是否可以點擊首頁和上一頁按鈕
///
public bool CanGoFirstOrPrev
{
get
{
if (PageIndex <= 1) return false;
return true;
}
}
///
/// 是否可以點擊最后頁和下一頁按鈕
///
public bool CanGoLastOrNext
{
get
{
if (PageIndex >= PageCount) return false;
return true;
}
}
#endregion
///
/// 點擊首頁按鈕
///
///
///
private void btnFirst_Click(object sender, RoutedEventArgs e)
{
OnPageChanging(1);
}
///
/// 點擊上一頁按鈕
///
///
///
private void btnPrev_Click(object sender, RoutedEventArgs e)
{
OnPageChanging(this.PageIndex - 1);
}
///
/// 點擊下一頁按鈕
///
///
///
private void btnNext_Click(object sender, RoutedEventArgs e)
{
OnPageChanging(this.PageIndex + 1);
}
///
/// 點擊末頁按鈕
///
///
///
private void btnLast_Click(object sender, RoutedEventArgs e)
{
OnPageChanging(this.PageCount);
}
///
/// 點擊跳轉按鈕
///
///
///
private void btnGoTo_Click(object sender, RoutedEventArgs e)
{
int pageIndex = 1;
try
{
pageIndex = Convert.ToInt32(txtPageIndex.Text);
}
catch
{
}
finally
{
OnPageChanging(pageIndex);
}
}
///
/// 頁碼更改
///
///
internal void OnPageChanging(int pageIndex)
{
if (pageIndex < 1) pageIndex = 1;
if (pageIndex > this.PageCount) pageIndex = this.PageCount;
var oldPageIndex = this.PageIndex;
var newPageIndex = pageIndex;
var eventArgs = new PageChangingEventArgs() { OldPageIndex = oldPageIndex, NewPageIndex = newPageIndex };
if (this.PageChanging != null)
{
this.PageChanging(this, eventArgs);
}
if (!eventArgs.IsCancel)
{
this.PageIndex = newPageIndex;
if (this.PageChanged != null)
{
this.PageChanged.Invoke(this, new PageChangedEventArgs() { CurrentPageIndex = this.PageIndex });
}
}
}
///
/// 通知導航按鈕(首頁,上一頁,下一頁,末頁)狀態的更改
///
void ChangeNavigationButtonState()
{
this.NotifyPropertyChanged("CanGoFirstOrPrev");
this.NotifyPropertyChanged("CanGoLastOrNext");
}
///
/// 初始化數據
///
void InitData()
{
if (this.TotalCount == 0)
{
this.PageCount = 1;
}
else
{
this.PageCount = this.TotalCount % this.PageSize > 0 ? (this.TotalCount / this.PageSize) + 1 : this.TotalCount / this.PageSize;
}
if (this.PageIndex < 1)
{
this.PageIndex = 1;
}
if (this.PageIndex > this.PageCount)
{
this.PageIndex = this.PageCount;
}
if (this.PageSize < 1)
{
this.PageSize = 20;
}
}
#region INotifyPropertyChanged成員
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
Xaml中使用如下:
<my:DataPager PageChanged="dataPager1_PageChanged" PageChanging="dataPager1_PageChanging" TotalCount="{Binding TotalCount}" PageSize="20" PageIndex="{Binding PageIndex}" x:Name="dataPager1" VerticalAlignment="Top" />
