在WPF中,一般會選用DataGrid/ListView進行數據展現,若是數據量很少,能夠直接一個頁面顯示出來。若是數據量很大,2000條數據,一次性顯示在一個頁面中,不只消耗資源,並且用戶體驗也很糟糕。這篇博客將介紹如何建立一個分頁控件。ide
爲了簡單起見,這個分頁控件目前只有 首頁/上一頁/下一頁/末頁/總頁數/第幾頁 等功能。實現思路,首頁/上一頁/下一頁/末頁 這四個經過路由事件來實現,在使用時能夠使用命令進行綁定,或者直接使用都可。總頁數和第幾頁經過依賴屬性來實現,使用時將頁數進行綁定顯示便可。示例代碼以下:this
Pager控件:spa
<UserControl.Resources> <Style TargetType="{x:Type Button}"> <Setter Property="Width" Value="22"/> <Setter Property="Height" Value="22"/> </Style> </UserControl.Resources> <Grid> <StackPanel Orientation="Horizontal"> <Button x:Name="FirstPageButton" Margin="5,0" Click="FirstPageButton_Click"> <Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <Button x:Name="PreviousPageButton" Margin="0,0,5,0" Click="PreviousPageButton_Click"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="第"/> <Run x:Name="rCurrent" Text="0"/> <Run Text="頁"/> </TextBlock> <Button Margin="5,0" x:Name="NextPageButton" Click="NextPageButton_Click"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="4" CenterY="4" /> </Path.RenderTransform> </Path> </Button> <Button Margin="0,0,5,0" x:Name="LastPageButton" Click="LastPageButton_Click"> <Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="3" CenterY="5" /> </Path.RenderTransform> </Path> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="共"/> <Run x:Name="rTotal" Text="0"/> <Run Text="頁"/> </TextBlock> </StackPanel> </Grid>
C#:code
public partial class Pager : UserControl
{
public static RoutedEvent FirstPageEvent;
public static RoutedEvent PreviousPageEvent;
public static RoutedEvent NextPageEvent;
public static RoutedEvent LastPageEvent;
public static readonly DependencyProperty CurrentPageProperty;
public static readonly DependencyProperty TotalPageProperty;
public string CurrentPage
{
get { return (string)GetValue(CurrentPageProperty); }
set { SetValue(CurrentPageProperty, value); }
}
public string TotalPage
{
get { return (string)GetValue(TotalPageProperty); }
set { SetValue(TotalPageProperty, value); }
}
public Pager()
{
InitializeComponent();
}
static Pager()
{
FirstPageEvent = EventManager.RegisterRoutedEvent("FirstPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
PreviousPageEvent = EventManager.RegisterRoutedEvent("PreviousPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
NextPageEvent = EventManager.RegisterRoutedEvent("NextPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
LastPageEvent = EventManager.RegisterRoutedEvent("LastPage", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Pager));
CurrentPageProperty = DependencyProperty.Register("CurrentPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnCurrentPageChanged)));
TotalPageProperty = DependencyProperty.Register("TotalPage", typeof(string), typeof(Pager), new PropertyMetadata(string.Empty,new PropertyChangedCallback(OnTotalPageChanged)));
}
public event RoutedEventHandler FirstPage
{
add { AddHandler(FirstPageEvent, value); }
remove { RemoveHandler(FirstPageEvent, value); }
}
public event RoutedEventHandler PreviousPage
{
add { AddHandler(PreviousPageEvent, value); }
remove { RemoveHandler(PreviousPageEvent, value); }
}
public event RoutedEventHandler NextPage
{
add { AddHandler(NextPageEvent, value); }
remove { RemoveHandler(NextPageEvent, value); }
}
public event RoutedEventHandler LastPage
{
add { AddHandler(LastPageEvent, value); }
remove { RemoveHandler(LastPageEvent, value); }
}
public static void OnTotalPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager;
if(p != null)
{
Run rTotal = (Run)p.FindName("rTotal");
rTotal.Text = (string)e.NewValue;
}
}
private static void OnCurrentPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Pager p = d as Pager;
if(p != null)
{
Run rCurrrent = (Run)p.FindName("rCurrent");
rCurrrent.Text = (string)e.NewValue;
}
}
private void FirstPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(FirstPageEvent, this));
}
private void PreviousPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(PreviousPageEvent, this));
}
private void NextPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(NextPageEvent, this));
}
private void LastPageButton_Click(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(LastPageEvent, this));
}
}
在MainWindow中,
XAML:orm
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <DataGrid Grid.Row="0" ItemsSource="{Binding FakeSource}" AutoGenerateColumns="False" CanUserAddRows="False"> <DataGrid.Columns> <DataGridTextColumn Header="Item Id" Binding="{Binding Id}" Width="80"/> <DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/> </DataGrid.Columns> </DataGrid> <local:Pager TotalPage="{Binding TotalPage}" CurrentPage="{Binding CurrentPage, Mode=TwoWay}" HorizontalAlignment="Center" Grid.Row="1"> <i:Interaction.Triggers> <i:EventTrigger EventName="FirstPage"> <i:InvokeCommandAction Command="{Binding FirstPageCommand}" /> </i:EventTrigger> <i:EventTrigger EventName="PreviousPage"> <i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/> </i:EventTrigger> <i:EventTrigger EventName="NextPage"> <i:InvokeCommandAction Command="{Binding NextPageCommand}" /> </i:EventTrigger> <i:EventTrigger EventName="LastPage"> <i:InvokeCommandAction Command="{Binding LastPageCommand}"/> </i:EventTrigger> </i:Interaction.Triggers> </local:Pager> </Grid>
MainViewModel類:blog
public class MainViewModel : ViewModel { private ICommand _firstPageCommand; public ICommand FirstPageCommand { get { return _firstPageCommand; } set { _firstPageCommand = value; } } private ICommand _previousPageCommand; public ICommand PreviousPageCommand { get { return _previousPageCommand; } set { _previousPageCommand = value; } } private ICommand _nextPageCommand; public ICommand NextPageCommand { get { return _nextPageCommand; } set { _nextPageCommand = value; } } private ICommand _lastPageCommand; public ICommand LastPageCommand { get { return _lastPageCommand; } set { _lastPageCommand = value; } } private int _pageSize; public int PageSize { get { return _pageSize; } set { if(_pageSize != value) { _pageSize = value; OnPropertyChanged("PageSize"); } } } private int _currentPage; public int CurrentPage { get { return _currentPage; } set { if(_currentPage != value) { _currentPage = value; OnPropertyChanged("CurrentPage"); } } } private int _totalPage; public int TotalPage { get { return _totalPage; } set { if(_totalPage != value) { _totalPage = value; OnPropertyChanged("TotalPage"); } } } private ObservableCollection<FakeDatabase> _fakeSoruce; public ObservableCollection<FakeDatabase> FakeSource { get { return _fakeSoruce; } set { if(_fakeSoruce != value) { _fakeSoruce = value; OnPropertyChanged("FakeSource"); } } } private List<FakeDatabase> _source; public MainViewModel() { _currentPage = 1; _pageSize = 20; FakeDatabase fake = new FakeDatabase(); _source = fake.GenerateFakeSource(); _totalPage = _source.Count / _pageSize; _fakeSoruce = new ObservableCollection<FakeDatabase>(); List<FakeDatabase> result = _source.Take(20).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); _firstPageCommand = new DelegateCommand(FirstPageAction); _previousPageCommand = new DelegateCommand(PreviousPageAction); _nextPageCommand = new DelegateCommand(NextPageAction); _lastPageCommand = new DelegateCommand(LastPageAction); } private void FirstPageAction() { CurrentPage = 1; var result = _source.Take(_pageSize).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); } private void PreviousPageAction() { if(CurrentPage == 1) { return; } List<FakeDatabase> result = new List<FakeDatabase>(); if(CurrentPage == 2) { result = _source.Take(_pageSize).ToList(); } else { result = _source.Skip((CurrentPage - 2) * _pageSize).Take(_pageSize).ToList(); } _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); CurrentPage--; } private void NextPageAction() { if(CurrentPage == _totalPage) { return; } List<FakeDatabase> result = new List<FakeDatabase>(); result = _source.Skip(CurrentPage * _pageSize).Take(_pageSize).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); CurrentPage++; } private void LastPageAction() { CurrentPage = TotalPage; int skipCount = (_totalPage - 1) * _pageSize; int takeCount = _source.Count - skipCount; var result = _source.Skip(skipCount).Take(takeCount).ToList(); _fakeSoruce.Clear(); _fakeSoruce.AddRange(result); } }
綁定到UI的數據源只是須要顯示的數據,不會把全部數據都取出來。當選擇顯示頁數時,只須要將新的數據源附上便可。
事件
總結:若是須要對該分頁控件進行擴展,例如,增長每頁顯示條數功能,只須要在Pager控件中增長相應的依賴屬性便可。ip
感謝您的閱讀,代碼點擊這裏下載。資源