我已经搜索了一个在多列上对DataGridView进行排序的示例,但似乎无法找到符合我想要的示例 .
基本上,我有一个绑定的DataGridView控件(绑定到DataTable / DataView),绑定的DataTable有两列: - priority和date . 我想按优先顺序按日期排序 . 也就是说,优先级列采用优先级,然后是日期,但两者都可以是升序或降序 .
因此,例如,我可能具有低优先级,早期日期优先(按优先级asc,日期asc排序),并且通过单击日期列 Headers ,切换到低优先级,晚期日期优先(按优先级顺序asc,日期desc) . 如果我然后单击优先级,我希望首先具有高优先级,然后是较晚的日期(日期列的当前排序顺序 - 按优先级desc排序,日期desc),但是然后可以单击日期列 Headers 切换到高优先级,早期日期(按优先级desc,日期asc排序) .
理想情况下,我想在两列上对字形进行排序以显示升序或降序 .
我们将非常感激地提出任何想法或建议 .
这个(见下文)似乎非常接近,但字形无法正常工作 .
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
DataSet1 dataset;
public Form1()
{
InitializeComponent();
dataset = new DataSet1(); // two columns: Priority(Int32) and date (DateTime)
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("01-jan-10"));
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("02-jan-10"));
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("03-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("04-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("05-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("06-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("07-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("08-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("09-jan-10"));
dataGridView1.DataSource = dataset.DataTable1.DefaultView;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic;
dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
}
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
DataGridViewColumn[] column = new[] { dataGridView1.Columns[0], dataGridView1.Columns[1] };
DataGridViewColumnHeaderCell headerCell = dataGridView1.Columns[e.ColumnIndex].HeaderCell;
if (headerCell.SortGlyphDirection != SortOrder.Ascending)
headerCell.SortGlyphDirection = SortOrder.Ascending;
else
headerCell.SortGlyphDirection = SortOrder.Descending;
String sort = column[0].DataPropertyName + " " + fnSortDirection(column[0])
+ ", "
+ column[1].DataPropertyName + " " + fnSortDirection(column[1]);
dataset.DataTable1.DefaultView.Sort = sort;
this.textBox1.Text = sort;
}
private String fnSortDirection(DataGridViewColumn column)
{
return column.HeaderCell.SortGlyphDirection != SortOrder.Descending ? "asc" : "desc";
}
}
}
5 回答
这是一个像google电子表格一样的示例 - 单击每列按此列排序,然后再次单击列交换搜索方向 . 此外,它按照您单击列的历史记录的相反顺序进行搜索,即如果单击列D然后是B然后是C然后是A,在最后一次点击它将按A,C,B,D列排序,并在最近点击该列时搜索的每个方向排序 .
它依赖于DataGridView内置的这些功能:
如果DataGridView有一个DataView作为其DataSource,那么为该DataView设置Sort字符串会立即导致DataView排序,并且该排序会立即显示在绑定的DataGridView控件中
排序字符串可以包含多个列,每个列都可以指示对ASC或DESC进行排序
当您设置DataView的排序字符串(从而使其排序)时,它所绑定的DataGridView将根据排序字符串中的第一项(名称和方向)自动添加适当的上下字形
我们从分拣机对象开始:
然后将我们的Sorter对象收集到Sorters类中:
我创建了自己的MultiSortingDataGridView类,派生自DataGridView,使用重写的Sort方法跟踪您单击的列,并根据列的历史记录导致一种DataView作为网格的绑定DataSource排序点击:
然后在我的表单中,我确保使用MultiSortingDataGridView控件(如上所述)而不是常规的DataGridView,并设置其数据源如下:
我第一次看到这个,我完全错过了同时按多列排序的部分(我的错,不是你的;问题非常清楚) .
如果是这种情况,您将不得不编写自己处理此问题的代码 . 默认情况下,提供的
DataGridView
控件不支持多列排序 . 幸运的是,其他人已经为你实现了很多工作 . 以下是一些示例:DataGridView Multi-column Sort(CodeProject)
How To Allow To Sort By Multiple Columns in Custom Data Binding(CodeProject)
或者,如果将
DataGridView
绑定到数据源,则可以在多个列上对该数据源进行排序,并且DataGridView
控件将遵循该排序 . 任何实现IBindingListView
并公开Sort
属性的数据源都可用于多列排序 .但是,无论您选择启用多列排序的路径如何,在强制
DataGridView
在多列上显示排序箭头标志符号方面都不会有太大成功 . 这里最简单的解决方案是自定义绘制列 Headers 以提供您自己的排序标志符号 .为此,请将处理程序附加到DataGridView.CellPainting event并检查
RowIndex
为-1(表示列 Headers ) . 有一个所有者绘制的列 Headers here的完整示例 . 我强烈建议坚持使用传统的箭头图标,但一旦你走这条路线,选项真的是无限的 . 您可以使列 Headers 看起来像您想要的任何内容,甚至可以使用不同的图标指示排序顺序中每列的相对权重 .您还可以选择从DataGridViewColumnHeaderCell派生新类并覆盖其Paint method . 这可能是一种更清洁,更面向对象的方式来完成同样的事情 .
DataGridView 在所有情况下都绑定到 DataSource (DataView,BindingSource,Table,DataSet "tablename"),它引用 DataView . 获取对此DataView的引用并根据需要设置 Sort (和 Filter ):
注意: Column names used in Sort and Filter correspond to the column names in DataTable ,DataGridView中的列名是用于绑定的基础数据属性名称(类的属性名称,DataTables的列名称等) . 您可以像这样在DataView中使用列名:
取决于您如何跟踪排序列(colSequence,colName,asc / desc,dgvColIdx),您可以决定如何构建Sort和Filter表达式并在dgv中设置SortGlyph(为简单起见,我制作了硬编码) .
好 .
根据Cody的上述建议,我现在有了一些似乎按预期工作的东西 . 我已经对HeaderCell进行了分类并覆盖了Paint方法(但是通过在base.Paint之前立即设置SortGlyphDirection来欺骗),DGV现在绘制了多个排序字形 .
我在这里从来没有回答过一个问题,所以如果格式不正确我会道歉,但我找到了这个问题的答案,这对未来的访问者来说可能更简单 . (见http://www.pcreview.co.uk/threads/datagridview-glyphs.3145090/)