前言
在现代桌面应用程序开发中,WPF 结合 Material Design 和 Prism 框架能够实现美观且功能强大的用户界面。
本文将详细介绍如何使用 WPF、MaterialDesign、Prism 8 和 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);
}
}
}
}
代码截图
总结
通过本文的介绍,我们成功实现了使用 WPF、MaterialDesign、Prism 8 和 DataGrid 来展示带有分页功能的表格数据。
这种方法不仅提升了用户体验,还简化了开发流程。
希望本文能帮助大家更好地理解和应用这些技术,为桌面应用程序带来更优秀的功能和视觉效果。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!
转自:天才卧龙
链接:cnblogs.com/chenwolong/p/17925955.html
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!