wpf + MaterialDesign + Prism8 + DataGrid 实现表格数据+分页
十年河东,十年河西,莫欺少年穷
学完止境,精益求精
1、不分页,带有排序功能(每个字段都可以排序)
xaml 如下:
<UserControl x:Class="WpfApp.UserControls.UserView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Grid.RowDefinitions > <RowDefinition Height="auto"/> <RowDefinition/> <RowDefinition Height="45"/> </Grid.RowDefinitions> <!--<Border Background="Red" Height="40" Grid.Row="0"/>--> <DataGrid Grid.Row="1" AutoGenerateColumns="False" x:Name="MyDataGrid" CanUserAddRows="False" HeadersVisibility="All" ItemsSource="{Binding Books}"> <DataGrid.Columns> <DataGridCheckBoxColumn Binding="{Binding isSelected}" Header="选择"> <DataGridCheckBoxColumn.HeaderStyle> <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> </Style> </DataGridCheckBoxColumn.HeaderStyle> </DataGridCheckBoxColumn> <DataGridTextColumn Binding="{Binding bookNo}" Header="书号" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookName}" Header="书名" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookAutor}" Header="作者" Width="1*" IsReadOnly="True" /> <DataGridTextColumn Binding="{Binding bookCate}" Header="分类" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookSite}" Header="出版社" Width="1*" IsReadOnly="True" /> <DataGridTextColumn Binding="{Binding Path=bookDate,StringFormat='yyyy年MM月dd日'}" Header="出版时间" Width="1*" IsReadOnly="True"/> </DataGrid.Columns> </DataGrid> <!--<Grid Grid.Row="2"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Panel.ZIndex="1"> <TextBlock VerticalAlignment="Center" Opacity="0.8"> <Run Text="共"/> <Run Text="20"/> <Run Text="条"/> </TextBlock> <ComboBox VerticalAlignment="Center" Margin="10,0" BorderThickness="0" BorderBrush="Black" Opacity="0.8" x:Name="PageSize" > <behavior:Interaction.Triggers> <behavior:EventTrigger EventName="SelectionChanged"> <behavior:InvokeCommandAction Command="{Binding ComboBoxCommand}" CommandParameter="{Binding ElementName=PageSize,Path=SelectedItem}"/> </behavior:EventTrigger> </behavior:Interaction.Triggers> <ComboBoxItem IsSelected="True">10条/页</ComboBoxItem> <ComboBoxItem>20条/页</ComboBoxItem> <ComboBoxItem>30条/页</ComboBoxItem> --><!--<ComboBox.ItemTemplate> ItemsSource="{Binding PageSizeSource}" <DataTemplate> <ComboBoxItem Visibility="Collapsed" Content="{Binding text}" IsSelected="{Binding IsSelected}" Tag="{Binding text}"/> </DataTemplate> </ComboBox.ItemTemplate>--><!-- </ComboBox> <Button x:Name="FirstPageButton" Margin="7,0" > <Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="White" StrokeThickness="1" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <Button x:Name="PreviousPageButton" Margin="0,0,7,0"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="White" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="第"/> <Run x:Name="rCurrent" Text="0"/> <Run Text="页"/> </TextBlock> <Button Margin="7,0" x:Name="NextPageButton" > <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="White" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="4" CenterY="4" /> </Path.RenderTransform> </Path> </Button> <Button Margin="0,0,7,0" x:Name="LastPageButton"> <Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5" Stroke="White" StrokeThickness="1" Fill="White" 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>--> <Button Grid.Row="2" Command="{Binding BtnCmd}" CommandParameter="{Binding ElementName=MyDataGrid,Path=SelectedItem}" Content="点我" Cursor="Hand"/> </Grid> </UserControl>
数据上下文如下:
using Prism.Commands; using Prism.Mvvm; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using System.Windows; using WpfApp.UserControlModels; namespace WpfApp.ViewModels { public class UserViewModel : BindableBase { public DelegateCommand<BookDto> BtnCmd { get; private set; } private ObservableCollection<BookDto> books; public ObservableCollection<BookDto> Books { get { return books; } set { books = value; RaisePropertyChanged(); } } //private ObservableCollection<string> foods; //public ObservableCollection<string> Foods //{ // get { return foods; } // set { foods = value; RaisePropertyChanged(); } //} public UserViewModel() { //Foods = new ObservableCollection<string>() { "app", "bpp" }; BtnCmd = new DelegateCommand<BookDto>(BtnClick); CreateBook(); } public void CreateBook() { Books = new ObservableCollection<BookDto>(); for (int i = 0; i < 25; i++) { BookDto dto = new BookDto() { bookAutor = "作者" + i, bookCate = "文学", bookDate = DateTime.Now.AddMonths(-i), bookName = "书名" + i, bookNo = "0813092" + i, bookPrice = 10, bookSite = "人民出版社" }; Books.Add(dto); } } private void BtnClick(BookDto obj) { if (obj.isSelected) MessageBox.Show(obj.bookName); } } }
model 如下:(后面还会继续使用该Model)
public class BookDto { public string bookNo { get; set; } public string bookName { get; set; } public string bookAutor { get; set; } public string bookSite { get; set; } public DateTime bookDate { get; set; } public string bookDateCn { get { return bookDate.ToString("yyyy-MM-dd"); } } public decimal bookPrice { get; set; } public string bookCate { get; set; } public bool isSelected { get; set; } = false; }
2、增加分页
xaml如下:
<UserControl x:Class="WpfApp.UserControls.UserView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <Grid.RowDefinitions > <RowDefinition Height="auto"/> <RowDefinition/> <RowDefinition Height="45"/> </Grid.RowDefinitions> <!--<Border Background="Red" Height="40" Grid.Row="0"/>--> <DataGrid Grid.Row="1" AutoGenerateColumns="False" x:Name="MyDataGrid" CanUserAddRows="False" HeadersVisibility="All" ItemsSource="{Binding Books}"> <DataGrid.Columns> <DataGridCheckBoxColumn Binding="{Binding isSelected}" Header="选择"> <DataGridCheckBoxColumn.HeaderStyle> <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}"> <Setter Property="HorizontalContentAlignment" Value="Center" /> </Style> </DataGridCheckBoxColumn.HeaderStyle> </DataGridCheckBoxColumn> <DataGridTextColumn Binding="{Binding bookNo}" Header="书号" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookName}" Header="书名" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookAutor}" Header="作者" Width="1*" IsReadOnly="True" /> <DataGridTextColumn Binding="{Binding bookCate}" Header="分类" Width="1*" IsReadOnly="True"/> <DataGridTextColumn Binding="{Binding bookSite}" Header="出版社" Width="1*" IsReadOnly="True" /> <DataGridTextColumn Binding="{Binding Path=bookDate,StringFormat='yyyy年MM月dd日'}" Header="出版时间" Width="1*" IsReadOnly="True"/> </DataGrid.Columns> </DataGrid> <Grid Grid.Row="2"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Panel.ZIndex="1"> <TextBlock VerticalAlignment="Center" Opacity="0.8"> <Run Text="共"/> <Run Text="{Binding TotalRecord}"/> <Run Text="条"/> </TextBlock> <ComboBox VerticalAlignment="Center" Margin="10,0" BorderThickness="0" BorderBrush="Black" Opacity="0.8" x:Name="PageSize" > <behavior:Interaction.Triggers> <behavior:EventTrigger EventName="SelectionChanged"> <behavior:InvokeCommandAction Command="{Binding ComboBoxCommand}" CommandParameter="{Binding ElementName=PageSize,Path=SelectedItem}"/> </behavior:EventTrigger> </behavior:Interaction.Triggers> <ComboBoxItem IsSelected="True">10条/页</ComboBoxItem> <ComboBoxItem>20条/页</ComboBoxItem> <ComboBoxItem>30条/页</ComboBoxItem> </ComboBox> <Button x:Name="FirstPageButton" Margin="7,0" Command="{Binding FirstPageCmd}"> <Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="White" StrokeThickness="1" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <Button x:Name="PreviousPageButton" IsEnabled="{Binding CanPrevious}" Margin="0,0,7,0" Command="{Binding PreviousPageCmd}"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="White" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Button> <TextBlock VerticalAlignment="Center"> <Run Text="第"/> <Run x:Name="rCurrent" Text="{Binding PageNumber}"/> <Run Text="页"/> </TextBlock> <Button Margin="7,0" x:Name="NextPageButton" IsEnabled="{Binding CanNext}" Command="{Binding NextPageCmd}"> <Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="White" Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center"> <Path.RenderTransform> <RotateTransform Angle="180" CenterX="4" CenterY="4" /> </Path.RenderTransform> </Path> </Button> <Button Margin="0,0,7,0" x:Name="LastPageButton" Command="{Binding LastPageCmd}"> <Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5" Stroke="White" StrokeThickness="1" Fill="White" 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="{Binding TotalPage}"/> <Run Text="页"/> </TextBlock> </StackPanel> </Grid> </Grid> </UserControl>
数据上下文如下:
using Prism.Commands; using Prism.Mvvm; using swapCommon.Pagination; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Windows; using WpfApp.UserControlModels; namespace WpfApp.ViewModels { public class UserViewModel : BindableBase { /// <summary> /// 页容量初始化 /// </summary> public int pagesize = 10; /// <summary> /// 最后一页事件 /// </summary> public DelegateCommand LastPageCmd { get; private set; } /// <summary> /// 第一页事件 /// </summary> public DelegateCommand FirstPageCmd { get; private set; } /// <summary> /// 上一页事件 /// </summary> public DelegateCommand PreviousPageCmd { get; private set; } /// <summary> /// 下一页事件 /// </summary> public DelegateCommand NextPageCmd { get; private set; } /// <summary> /// 下拉事件 /// </summary> public DelegateCommand<Object> ComboBoxCommand { get; private set; } /// <summary> /// 第几页 /// </summary> private int pageNumber; public int PageNumber { get { return pageNumber; } set { pageNumber = value; RaisePropertyChanged(); } } /// <summary> /// 记录条数 /// </summary> private int totalRecord; public int TotalRecord { get { return totalRecord; } set { totalRecord = value; RaisePropertyChanged(); } } /// <summary> /// 总页数 /// </summary> private int totalPage; public int TotalPage { get { return totalPage; } set { totalPage = value; RaisePropertyChanged(); } } /// <summary> /// 是否可以执行上一页 /// </summary> private bool canPrevious; public bool CanPrevious { get { return canPrevious; } set { canPrevious = value; RaisePropertyChanged(); } } /// <summary> /// 是否可以执行上一页 /// </summary> private bool canNext; public bool CanNext { get { return canNext; } set { canNext = value; RaisePropertyChanged(); } } /// <summary> /// 数据源 在此模拟数据库 /// </summary> public List<BookDto> dataSource { get; set; } /// <summary> /// 分页后的数据 /// </summary> private ObservableCollection<BookDto> books; public ObservableCollection<BookDto> Books { get { return books; } set { books = value; RaisePropertyChanged(); } } public UserViewModel() { ComboBoxCommand = new DelegateCommand<Object>(ComboBoxSelectionChanged); NextPageCmd = new DelegateCommand(NextPage); PreviousPageCmd = new DelegateCommand(PreviousPage); LastPageCmd = new DelegateCommand(LastPage); FirstPageCmd = new DelegateCommand(FirstPage); CreateBook(); } private void FirstPage() { PageNumber=1; //增加一页 CanPrevious = false; if (pageNumber > 1) { CanPrevious = true; //是否可以点击上一页 否 } TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 if (TotalPage > PageNumber) { CanNext = true;//是否可以点击下一页 } else { CanNext = false; } Books = new ObservableCollection<BookDto>(); var data = dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach (var item in data) { Books.Add(item); } } /// <summary> /// 最后一页 /// </summary> private void LastPage() { CanPrevious = false; TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 PageNumber = TotalPage;//最后一页 将总页码赋值给当前页 if (pageNumber > 1) { CanPrevious = true; //是否可以点击上一页 否 } if (TotalPage > PageNumber) { CanNext = true;//是否可以点击下一页 } else { CanNext = false; } Books = new ObservableCollection<BookDto>(); var data = dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach (var item in data) { Books.Add(item); } } /// <summary> /// 下一页 /// </summary> private void NextPage() { PageNumber ++; //增加一页 CanPrevious = false; if (pageNumber > 1) { CanPrevious = true; //是否可以点击上一页 否 } TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 if (TotalPage > PageNumber) { CanNext = true;//是否可以点击下一页 } else { CanNext = false; } Books = new ObservableCollection<BookDto>(); var data = dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach (var item in data) { Books.Add(item); } } private void PreviousPage() { PageNumber--; //增加一页 CanPrevious = false; if (pageNumber > 1) { CanPrevious = true; //是否可以点击上一页 否 } TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 if (TotalPage > PageNumber) { CanNext = true;//是否可以点击下一页 } else { CanNext = false; } Books = new ObservableCollection<BookDto>(); var data = dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach (var item in data) { Books.Add(item); } } /// <summary> /// /// </summary> /// <param name="obj"></param> private void ComboBoxSelectionChanged(Object obj) { if (obj != null) { var Content = ((System.Windows.Controls.ContentControl)obj).Content; switch (Content) { case "10条/页": pagesize = 10; ComboBoxSelectionInitData(); break; case "20条/页": pagesize = 20; ComboBoxSelectionInitData(); break; case "30条/页": pagesize = 30; ComboBoxSelectionInitData(); break; } } } /// <summary> /// 页码改变时 重新加载数据 /// </summary> void ComboBoxSelectionInitData() { // PageNumber = 1; //页码改变时 加载第一页 CanPrevious = false; //是否可以点击上一页 否 TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 if (TotalPage > 1) { CanNext = true;//是否可以点击下一页 } Books = new ObservableCollection<BookDto>(); var data = dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach (var item in data) { Books.Add(item); } } public void CreateBook() { dataSource = new List<BookDto>(); for (int i = 0; i < 252; i++) { BookDto dto = new BookDto() { bookAutor = "作者" + i, bookCate = "文学", bookDate = DateTime.Now.AddMonths(-i), bookName = "书名" + i, bookNo = "0813092" + i, bookPrice = 10, bookSite = "人民出版社" }; dataSource.Add(dto); } // PageNumber = 1; //默认加载第一页 CanPrevious = false; //是否可以点击上一页 否 TotalRecord = dataSource.Count; //总记录数 int pages = TotalRecord / pagesize; TotalPage = TotalRecord % pagesize == 0 ? pages : pages + 1; //总页数 if (TotalPage > 1) { CanNext = true;//是否可以点击下一页 } Books = new ObservableCollection<BookDto>(); var data= dataSource.Skip((PageNumber - 1) * pagesize).Take(pagesize); foreach(var item in data) { Books.Add(item); } } } }
代码截图
@陈大六的博客