新建Custom Control,名:PagingDataGrid

打开工程下面的Themes\Generic.xaml

xaml里面代码替换如下

复制代码
  1 <Style x:Key="{x:Type loc:PagingDataGrid}" TargetType="{x:Type loc:PagingDataGrid}">
  2         <Setter Property="Background"  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
  3         <Setter Property="Foreground"  Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  4         <Setter Property="BorderBrush" Value="#FF688CAF" />
  5         <Setter Property="BorderThickness" Value="1" />
  6         <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected" />
  7         <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
  8         <Setter Property="CanUserSortColumns" Value="False"/>
  9         <Setter Property="AlternatingRowBackground" Value="SkyBlue"/>
 10         <Setter Property="AlternationCount" Value="2"/>
 11         <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
 12         <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
 13         <Setter Property="Template">
 14             <Setter.Value>
 15                 <ControlTemplate TargetType="{x:Type loc:PagingDataGrid}">
 16                     <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True" Padding="{TemplateBinding Padding}">
 17                         <Grid>
 18                             <Grid.RowDefinitions>
 19                                 <RowDefinition Height="*"/>
 20                                 <RowDefinition Height="Auto"/>
 21                             </Grid.RowDefinitions>
 22                             <ScrollViewer Grid.Row="0" Focusable="false" Name="DG_ScrollViewer">
 23                                 <ScrollViewer.Template>
 24                                     <ControlTemplate TargetType="{x:Type ScrollViewer}">
 25                                         <Grid>
 26                                             <Grid.ColumnDefinitions>
 27                                                 <ColumnDefinition Width="Auto"/>
 28                                                 <ColumnDefinition Width="*"/>
 29                                                 <ColumnDefinition Width="Auto"/>
 30                                             </Grid.ColumnDefinitions>
 31                                             <Grid.RowDefinitions>
 32                                                 <RowDefinition Height="Auto"/>
 33                                                 <RowDefinition Height="*"/>
 34                                                 <RowDefinition Height="Auto"/>
 35                                             </Grid.RowDefinitions>
 36                                             <Button Command="ApplicationCommands.SelectAll" Focusable="False" Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}">
 37                                                 <Button.Visibility>
 38                                                     <Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
 39                                                         <Binding.ConverterParameter>
 40                                                             <DataGridHeadersVisibility>All</DataGridHeadersVisibility>
 41                                                         </Binding.ConverterParameter>
 42                                                     </Binding>
 43                                                 </Button.Visibility>
 44                                             </Button>
 45                                             <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1">
 46                                                 <DataGridColumnHeadersPresenter.Visibility>
 47                                                     <Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
 48                                                         <Binding.ConverterParameter>
 49                                                             <DataGridHeadersVisibility>Column</DataGridHeadersVisibility>
 50                                                         </Binding.ConverterParameter>
 51                                                     </Binding>
 52                                                 </DataGridColumnHeadersPresenter.Visibility>
 53                                             </DataGridColumnHeadersPresenter>
 54                                             <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" Grid.ColumnSpan="2" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Grid.Row="1"/>
 55                                             <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
 56                                             <Grid Grid.Column="1" Grid.Row="2">
 57                                                 <Grid.ColumnDefinitions>
 58                                                     <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}"/>
 59                                                     <ColumnDefinition Width="*"/>
 60                                                 </Grid.ColumnDefinitions>
 61                                                 <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
 62                                             </Grid>
 63                                         </Grid>
 64                                     </ControlTemplate>
 65                                 </ScrollViewer.Template>
 66                                 <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
 67                             </ScrollViewer>
 68                             <!--分页控件-->
 69                             <StackPanel Grid.Row="1" SnapsToDevicePixels="True" VerticalAlignment="Center" Visibility="{Binding IsShowPaging,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BoolToVisibilityConverter}}" Orientation="Horizontal">
 70                                 <StackPanel.Resources>
 71                                     <Style TargetType="TextBlock">
 72                                         <Setter Property="FontSize" Value="13"/>
 73                                         <Setter Property="Margin" Value="3,0"/>
 74                                     </Style>
 75                                     <Style TargetType="TextBox">
 76                                         <Setter Property="FontSize" Value="13"/>
 77                                     </Style>
 78                                     <Style TargetType="ComboBox">
 79                                         <Setter Property="FontSize" Value="13"/>
 80                                     </Style>
 81                                     <Style TargetType="Button">
 82                                         <Setter Property="FontSize" Value="13"/>
 83                                     </Style>
 84                                 </StackPanel.Resources>
 85                                 <TextBlock>总计</TextBlock>
 86                                 <TextBlock Foreground="Red" Text="{Binding Total,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" />
 87                                 <TextBlock>条记录 每页显示</TextBlock>
 88                                 <ComboBox x:Name="PART_DispalyCount" BorderThickness="1" BorderBrush="Red" Foreground="Red" Grid.Column="0" FontSize="12"  VerticalAlignment="Center" MinWidth="40" ItemsSource="{Binding PageSizeItemsSource,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"  SelectedItem="{Binding PageSize,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
 89                                 <TextBlock>条 总页数</TextBlock>
 90                                 <TextBlock Margin="3" Foreground="Red" Text="{Binding PageCount,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" />
 91                                 <Button x:Name="PART_PrePage" Content="上一页"/>
 92                                 <TextBlock>当前页</TextBlock>
 93                                 <TextBox Width="100" Foreground="Red" x:Name="PART_PageIndex" Text="{Binding PageIndex,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" />
 94                                 <TextBlock>页</TextBlock>
 95                                 <Button x:Name="PART_GoTo" Content="转到页"/>
 96                                 <Button x:Name="PART_NextPage" Content="下一页"/>
 97                             </StackPanel>
 98                         </Grid>
 99                     </Border>
100                 </ControlTemplate>
101             </Setter.Value>
102         </Setter>
103         <Style.Triggers>
104             <Trigger Property="IsGrouping" Value="true">
105                 <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
106             </Trigger>
107         </Style.Triggers>
108     </Style>
复制代码


打开PagingDataGrid.cs文件

代码如下:

复制代码
  1 public class PagingDataGrid : DataGrid
  2     {
  3         static PagingDataGrid()
  4         {
  5             DefaultStyleKeyProperty.OverrideMetadata(typeof(PagingDataGrid), new FrameworkPropertyMetadata(typeof(PagingDataGrid)));
  6         }
  7 
  8         #region 变量定义
  9         ComboBox PART_DispalyCount;
 10         Button PART_PrePage;
 11         Button PART_NextPage;
 12         Button PART_GoTo;
 13         TextBox PART_PageIndex;
 14         #endregion
 15 
 16         #region 事件代理
 17 
 18         public delegate void PagingChangedEventHandler(object sender, PagingChangedEventArgs e);
 19 
 20         public event PagingChangedEventHandler PagingChanged;
 21 
 22         private void OnPagingChanged()
 23         {
 24             if (PagingChanged != null)
 25             {
 26                 PagingChanged(this, new PagingChangedEventArgs() { PageIndex = PageIndex, PageSize = PageSize });
 27             }
 28         }
 29         #endregion
 30 
 31         #region 一般属性
 32         private List<Student> dataItems = new List<Student>();
 33 
 34         public List<Student> DataItems
 35         {
 36             get
 37             {
 38                 return dataItems;
 39             }
 40             set
 41             {
 42                 dataItems = value;
 43                 ReCalcLayout();
 44             }
 45         }
 46 
 47         List<int> list = new List<int>();
 48 
 49         public List<int> PageSizeItemsSource
 50         {
 51             get
 52             {
 53                 return list;
 54             }
 55             set
 56             {
 57                 list = value;
 58             }
 59         } 
 60         #endregion
 61 
 62         #region 依赖属性
 63         /// <summary>
 64         /// 页大小
 65         /// </summary>
 66         public int PageSize
 67         {
 68             get { return (int)GetValue(PageSizeProperty); }
 69             set { SetValue(PageSizeProperty, value); }
 70         }
 71 
 72         /// <summary>
 73         /// 当前页
 74         /// </summary>
 75         public int PageIndex
 76         {
 77             get { return (int)GetValue(PageIndexProperty); }
 78             set { SetValue(PageIndexProperty, value); }
 79         }
 80 
 81         /// <summary>
 82         /// 总计录数
 83         /// </summary>
 84         public int Total
 85         {
 86             get { return (int)GetValue(TotalProperty); }
 87             set { SetValue(TotalProperty, value); }
 88         }
 89 
 90         /// <summary>
 91         /// 是否显示页
 92         /// </summary>
 93         public bool IsShowPaging
 94         {
 95             get { return (bool)GetValue(IsShowPagingProperty); }
 96             set { SetValue(IsShowPagingProperty, value); }
 97         }
 98 
 99         /// <summary>
100         /// 总页数
101         /// </summary>
102         public int PageCount
103         {
104             get { return (int)GetValue(PageCountProperty); }
105             set { SetValue(PageCountProperty, value); }
106         }
107 
108 
109 
110         // Using a DependencyProperty as the backing store for PageCount.  This enables animation, styling, binding, etc...
111         public static readonly DependencyProperty PageCountProperty =
112             DependencyProperty.Register("PageCount", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(5));
113 
114 
115         // Using a DependencyProperty as the backing store for End.  This enables animation, styling, binding, etc...
116         public static readonly DependencyProperty EndProperty =
117             DependencyProperty.Register("End", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(0));
118 
119 
120         // Using a DependencyProperty as the backing store for Start.  This enables animation, styling, binding, etc...
121         public static readonly DependencyProperty StartProperty =
122             DependencyProperty.Register("Start", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(0));
123 
124 
125         // Using a DependencyProperty as the backing store for IsShowPaging.  This enables animation, styling, binding, etc...
126         public static readonly DependencyProperty IsShowPagingProperty =
127             DependencyProperty.Register("IsShowPaging", typeof(bool), typeof(PagingDataGrid), new UIPropertyMetadata(true));
128 
129 
130         // Using a DependencyProperty as the backing store for Total.  This enables animation, styling, binding, etc...
131         public static readonly DependencyProperty TotalProperty =
132             DependencyProperty.Register("Total", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(16));
133 
134 
135         // Using a DependencyProperty as the backing store for PageIndex.  This enables animation, styling, binding, etc...
136         public static readonly DependencyProperty PageIndexProperty =
137             DependencyProperty.Register("PageIndex", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(1));
138 
139 
140         // Using a DependencyProperty as the backing store for PageSize.  This enables animation, styling, binding, etc...
141         public static readonly DependencyProperty PageSizeProperty =
142             DependencyProperty.Register("PageSize", typeof(int), typeof(PagingDataGrid), new UIPropertyMetadata(10));
143 
144         #endregion
145 
146         #region 相关命令
147         RoutedCommand NextPageCommand = new RoutedCommand();
148         RoutedCommand PrePageCommand = new RoutedCommand();
149         RoutedCommand GoToCommand = new RoutedCommand();
150         #endregion
151 
152         #region 重写方法
153         public override void OnApplyTemplate()
154         {
155             base.OnApplyTemplate();
156             //获取模板中的控件  
157             PART_DispalyCount = GetTemplateChild("PART_DispalyCount") as ComboBox;
158             PART_PrePage = GetTemplateChild("PART_PrePage") as Button;
159             PART_NextPage = GetTemplateChild("PART_NextPage") as Button;
160             PART_GoTo = GetTemplateChild("PART_GoTo") as Button;
161             PART_PageIndex = GetTemplateChild("PART_PageIndex") as TextBox;
162             //添加控件命令Binding  
163             PART_NextPage.CommandBindings.Add(new CommandBinding(NextPageCommand, NextPage_Excuted, NextPage_CanExcuted));
164             PART_PrePage.CommandBindings.Add(new CommandBinding(PrePageCommand, PrePage_Excuted, PrePage_CanExcuted));
165             PART_GoTo.CommandBindings.Add(new CommandBinding(GoToCommand, GoTo_Excuted, GoTo_CanExcuted));
166             PART_NextPage.Command = NextPageCommand;
167             PART_PrePage.Command = PrePageCommand;
168             PART_GoTo.Command = GoToCommand;
169             //添加控件事件
170             PART_DispalyCount.SelectionChanged += PART_DispalyCount_SelectionChanged;
171         }
172 
173         private void GoTo_Excuted(object sender, ExecutedRoutedEventArgs e)
174         {
175             int idx = 0;
176             if (int.TryParse(PART_PageIndex.Text, out idx))
177             {
178                 GoTo(idx);
179             }
180         }
181 
182         private void GoTo_CanExcuted(object sender, CanExecuteRoutedEventArgs e)
183         {
184             int idx = 0;
185             if (int.TryParse(PART_PageIndex.Text, out idx))
186             {
187                 if (idx > PageCount || idx <= 0)
188                 {
189                     e.CanExecute = false;
190                 }
191                 else
192                 {
193                     e.CanExecute = true;
194                 }
195             }
196             else
197             {
198                 e.CanExecute = false;
199             }
200         }
201 
202         private void NextPage_CanExcuted(object sender, CanExecuteRoutedEventArgs e)
203         {
204             if (PageIndex == PageCount)
205             {
206                 e.CanExecute = false;
207             }
208             else
209             {
210                 e.CanExecute = true;
211             }
212         }
213 
214         private void NextPage_Excuted(object sender, ExecutedRoutedEventArgs e)
215         {
216             GoTo(PageIndex++);            
217         }
218 
219         private void PrePage_CanExcuted(object sender, CanExecuteRoutedEventArgs e)
220         {
221             if (PageIndex == 1)
222             {
223                 e.CanExecute = false;
224             }
225             else
226             {
227                 e.CanExecute = true;
228             }
229         }
230 
231         private void PrePage_Excuted(object sender, ExecutedRoutedEventArgs e)
232         {
233             GoTo(PageIndex--);
234         }
235         #endregion
236 
237         #region 分页事件
238         void PART_DispalyCount_SelectionChanged(object sender, SelectionChangedEventArgs e)
239         {
240             PageSize = int.Parse((sender as ComboBox).SelectedItem.ToString());
241             ReCalcLayout();
242             GoTo(PageIndex);
243         }
244 
245         private void GoTo(int page)
246         {
247             ItemsSource = DataItems.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
248         }
249 
250         private void ReCalcLayout()
251         {
252             Total = DataItems.Count;
253             int pc = Total / PageSize;
254             if (Total % PageSize == 0)
255             {
256                 PageCount = pc;
257             }
258             else
259             {
260                 PageCount = pc + 1;
261             }
262             PageIndex = PageIndex > PageCount ? PageCount : PageIndex;
263         }
264         #endregion
265     }
复制代码


此外还需要一个类支持PagingChangedEventArgs

复制代码
1 /// <summary>
2     /// 页跳转参数
3     /// </summary>
4     public class PagingChangedEventArgs : EventArgs
5     {
6         public int PageSize { get; set; }
7         public int PageIndex { get; set; }
8     }
复制代码


控件完成,调试:

复制代码
 1 <local:PagingDataGrid x:Name="pdg" PagingChanged="pdg_PagingChanged" IsShowPaging="True" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" SnapsToDevicePixels="True" CanUserReorderColumns="False">
 2                             <local:PagingDataGrid.PageSizeItemsSource>
 3                                 <sys:Int32>5</sys:Int32>
 4                                 <sys:Int32>10</sys:Int32>
 5                                 <sys:Int32>15</sys:Int32>
 6                                 <sys:Int32>20</sys:Int32>
 7                                 <sys:Int32>30</sys:Int32>
 8                                 <sys:Int32>50</sys:Int32>
 9                                 <sys:Int32>100</sys:Int32>
10                             </local:PagingDataGrid.PageSizeItemsSource>
11                             <local:PagingDataGrid.Columns>
12                                 <DataGridTextColumn Binding="{Binding Name}" Header="AAA"/>
13                                 <DataGridTextColumn Binding="{Binding Age}" Header="BBB"/>
14                                 <DataGridTextColumn Binding="{Binding Sex}" Width="*" Header="CCC"/>
15                             </local:PagingDataGrid.Columns>
16                         </local:PagingDataGrid>
复制代码

新建调试类Student

复制代码
1     public class Student
2     {
3         public string Name { get; set; }
4         public int Age { get; set; }
5         public string MoreInfo { get; set; }
6     }
复制代码

调试代码,注意这里使用DataItems保存信息,如果使用Items或是ItemsSource则无分页效果

复制代码
1 List<Student> list = new List<Student>();
2             for (int i = 0; i < 20; i++)
3             {
4                 list.Add(new Student() { Name = Guid.NewGuid().ToString(), Age = i, MoreInfo = "Sex" });
5             }
6             pdg.DataItems = list;
复制代码