在多列上对 DataGridView 进行排序? [英] Sort a DataGridView on multiple columns?

查看:30
本文介绍了在多列上对 DataGridView 进行排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经搜索了一个在多列上对 DataGridView 进行排序的示例,但似乎无法找到一个可以执行我想要的示例.

I've searched for an example of sorting a DataGridView on multiple columns, but don't seem to be able to find an example which does what I would like.

基本上,我有一个绑定的 DataGridView 控件(绑定到 DataTable/DataView),并且绑定的 DataTable 有两列:-优先级和日期.我想在优先级内按日期排序.也就是说,优先级列优先,然后是日期,但两者都可以升序或降序.

Basically, I have a bound DataGridView control (bound to a DataTable/DataView), and the bound DataTable has two columns:- priority and date. I would like to sort by date within priority. That is, the priority column takes precendence, then its the date but both can be ascending or descending.

所以,例如,我可能有低优先级,最早的日期优先(按优先级升序排列,日期升序),然后,通过单击日期列标题,切换到低优先级,晚日期首先(按优先级升序,日期降序).如果我然后点击优先级,我想先有高优先级,然后是晚日期(日期列的当前排序顺序 - 按优先级 desc、date desc 排序),但是然后能够点击日期列标题切换到高优先级,提前日期(order by priority desc, date asc).

So, for example, I may have low priority, early date first (order by priority asc, date asc), and, by clicking the date column header, switch to low priority, late date first (order by priority asc, date desc). If I then click on the priority, I would like to have high priority first, then late date (the current sort order for the date column - order by priority desc, date desc), but then be able to click the date column header to switch to high priority, early date (order by priority desc, date asc).

理想情况下,我希望对两列的字形进行排序以显示升序或降序.

Ideally, I would like sort glyphs on both columns to show ascending or descending.

如有任何想法或建议,我们将不胜感激.

Any ideas or pointers would be gratefully received.

这(见下文)似乎非常接近,但字形无法正常工作.

This (see below) seems to get pretty close, but the glyphs aren't working right.

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";
     }
  }
}

推荐答案

好的.

根据上述科迪的建议,我现在有一些似乎按预期工作的东西.我已经对 HeaderCell 进行了子类化并覆盖了 Paint 方法(但通过在 base.Paint 之前设置 SortGlyphDirection 作弊),并且 DGV 现在绘制多个排序字形.

Following from Cody's suggestions above, I now have something which seems to work as expected. I have sub-classed the HeaderCell and over-ridden the Paint method (but cheated by setting the SortGlyphDirection immediately prior to the base.Paint) and the DGV now paints multiple sorting glyphs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
  public partial class Form1 : Form
  {
     DataSet1 dataset;

     public Form1()
     {
        InitializeComponent();

        dataset = new DataSet1(); // three columns: Priority(Int32), Date (DateTime) and Description(String)
        dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("01-jan-10"), "this");
        dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("02-jan-10"), "is");
        dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("03-jan-10"), "a");
        dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("04-jan-10"), "sample");
        dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("05-jan-10"), "of");
        dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("06-jan-10"), "the");
        dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("07-jan-10"), "data");
        dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("08-jan-10"), "in");
        dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("09-jan-10"), "use");

        dataGridView1.DataSource = dataset.DataTable1.DefaultView;

        dataGridView1.AllowUserToAddRows = false;

        dataGridView1.Columns[0].HeaderCell = new MyDataGridViewColumnHeaderCell();
        dataGridView1.Columns[1].HeaderCell = new MyDataGridViewColumnHeaderCell();

        dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
        dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic;
     }

     private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
     {
        DataGridViewColumn clickedColumn = dataGridView1.Columns[e.ColumnIndex];

        if (clickedColumn.HeaderCell is MyDataGridViewColumnHeaderCell)
        {
           DoMultiColumnSort();
        }
        else
        {
           dataGridView1.Columns.OfType<DataGridViewColumn>()
                                .Where(column => column.HeaderCell is MyDataGridViewColumnHeaderCell)
                                .ForEach(column => ((MyDataGridViewColumnHeaderCell)column.HeaderCell).SortOrderDirection = SortOrder.None);
        }

        this.textBox1.Text = dataset.DataTable1.DefaultView.Sort;
     }

     private void DoMultiColumnSort()
     {
        var sortClauses = dataGridView1.Columns.OfType<DataGridViewColumn>()
                                               .Where(column => column.HeaderCell is MyDataGridViewColumnHeaderCell)
                                               .Select(column => GetSortClause(column));

        dataset.DataTable1.DefaultView.Sort = String.Join(",", sortClauses);
     }

     private String GetSortClause(DataGridViewColumn column)
     {
        SortOrder direction = column.HeaderCell.SortGlyphDirection;

        if (column.HeaderCell is MyDataGridViewColumnHeaderCell)
        {
           direction = ((MyDataGridViewColumnHeaderCell)column.HeaderCell).SortOrderDirection;
        }

        return column.DataPropertyName + " " + (direction == SortOrder.Descending ? "DESC" : "ASC");
     }
  }

  public partial class MyDataGridViewColumnHeaderCell : DataGridViewColumnHeaderCell
  {
     public SortOrder SortOrderDirection { get; set; } // defaults to zero = SortOrder.None;

     protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates dataGridViewElementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
     {
        this.SortGlyphDirection = this.SortOrderDirection;
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
     }

     public override object Clone()
     {
        MyDataGridViewColumnHeaderCell result = (MyDataGridViewColumnHeaderCell)base.Clone();
        result.SortOrderDirection = this.SortOrderDirection;
        return result;
     }

     protected override void OnClick(DataGridViewCellEventArgs e)
     {
        this.SortOrderDirection = (this.SortOrderDirection != SortOrder.Ascending) ? SortOrder.Ascending : SortOrder.Descending;
        base.OnClick(e);
     }
  }

  public static partial class Extensions
  {
     public static void ForEach<T>(this IEnumerable<T> value, Action<T> action) { foreach (T item in value) { action(item); } }
  }
}

这篇关于在多列上对 DataGridView 进行排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆