一、项目背景与问题引出
在以往的开发历程中,曾经构建了一个数据客户端,那时采用的是直接连接数据库的方式。然而,随着对系统架构的深入思考和实践经验的积累,如今我们认识到这种直接连接数据库的方式存在诸多弊端。为了提升系统的安全性、稳定性以及可维护性,我们决定对其进行重大改进,将其改为服务端采用 RESTful API 与客户端相结合的架构模式,把所有的数据处理工作都集中在服务端完成。
在这个重构的过程中,我们不可避免地遇到了一些新的问题。由于在之前的版本中没有采用分页机制,所以对于数据的排序操作,直接使用了 DataGrid 的默认排序功能即可满足需求。但是,现在随着服务端分页功能的引入,一些之前未曾显现的问题逐渐暴露了出来。为了更好地解决这些问题,我们将对整个排序过程进行深入分析并记录下来,以便为后续的开发工作提供参考和借鉴。
二、DataGrid 的排序属性设置
在 XAML 中,存在一个名为 dataGrid1 的 DataGrid。若要实现点击列头进行排序的功能,只需要在这个 DataGrid 上添加 Sorting 属性即可。具体的 XAML 代码如下:
在初始化的时候,我们可以为某一列指定排序方式。例如,以下代码展示了如何通过 C# 代码为数据列表指定排序:
ICollectionView view = CollectionViewSource.GetDefaultView(list);
view.SortDescriptions.Clear(); // 先清除所有的排序
SortDescription sd = new SortDescription("列名", ListSortDirection.Descending);
view.SortDescriptions.Add(sd);
同时,我们也可以在 XAML 中直接指定列的排序方式。假设列名为 movieName,那么对应的 XAML 代码如下:
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=movieName}" SortDirection="Ascending" SortMemberPath="movieName" Header="名称" />
</DataGrid.Columns>
三、主要排序方法分析与问题解决
下面来看主要的排序方法。首先,定义了一个名为 dataGrid1_Sorting 的方法,用于处理 DataGrid 的排序事件:
private void dataGrid1_Sorting(object sender, DataGridSortingEventArgs e)
{
e.Handled = true; // 这个设置可要可不要,目前还没有深入研究其具体影响。
pager.OrderColumn = e.Column.SortMemberPath;
ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
pager.Order = "asc"; // 默认升序
if (view.SortDescriptions.Count > 0)
{
if (view.SortDescriptions[0].PropertyName == e.Column.SortMemberPath)
{
if (view.SortDescriptions[0].Direction == System.ComponentModel.ListSortDirection.Ascending)
{
pager.Order = "desc";
}
else if (view.SortDescriptions[0].Direction == ListSortDirection.Descending)
{
pager.Order = "asc";
}
}
}
LoadData();
}
在这个方法中,e.Column.SortMemberPath 代表点击列头的列名。然而,我们发现了一个问题,那就是 e.Column.SortDirection 这个属性在某些情况下表现异常。如果在初始化的时候指定了排序,那么在第一次点击列头时能够正确获取到这个属性的值,但是在后续的点击中,这个属性就变成了 null 值。即使在初始化时没有指定排序,这个属性一开始也是 null 值。为了解决这个问题,我们尝试为它赋值,即 e.Column.SortDirection = ListSortDirection.Descending。但是令人困惑的是,在下一次点击时,它仍然会变为 null 值。经过长时间的摸索和尝试,我们采用了另一种方法。
首先,获取数据列表的视图:
ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid1.ItemsSource);
然后,可以从 view.SortDescriptions 中取得有排序的列。通过判断这个集合的元素数量是否大于 0 以及当前点击的列名是否与集合中的列名一致,如果当前是升序则将其变为降序,同时查询降序的数据。最后,执行清除排序再添加排序的操作,具体代码如下:
view.SortDescriptions.Clear(); // 先清除所有的排序
SortDescription sd = new SortDescription("列名", ListSortDirection.Descending);
view.SortDescriptions.Add(sd);
通过这种方式,我们实现了服务端的排序功能。但是,我们不禁思考,是否存在更加简单高效的方法来实现这个功能呢?希望在未来的开发过程中,能够找到更加优化的解决方案。