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