新建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;
