wpf + MaterialDesign + Prism8 + DataGrid 实现表格数据+分页

发布时间 2023-12-25 16:10:28作者: 天才卧龙

十年河东,十年河西,莫欺少年穷

学完止境,精益求精

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>
View Code

数据上下文如下:

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);
        }
    }
}
View Code

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;
    }
View Code

 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>
View Code

数据上下文如下:

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);
            }
        }
         
    }
}
View Code

代码截图

 

 @陈大六的博客