Microsoft Communities

Welcome to WindowsClient.net | Sign in | Join

Here are some frequently asked questions about Windows Forms and their answers.

Windows Forms FAQs

How do I sort on multiple columns?

By default the DataGridView control does not provide sorting on multiple columns. Depending upon if the DataGridView is databound or not, you can provide additional support for sorting on multiple columns.

Databound DataGridView

When the DataGridView is databound the datasource can be sorted on multiple columns and the DataGridView will respect that sorting, but the only the first sorted column will display the sort glyph. In addition, the SortedColumn property will only return the first sorted column.

Some datasources have built in support for sorting on multiple columns. If your datasource implements IBindingListView and provides support for the Sort property, then using it will provide support for multi-column sorting. To indicate in the grid that multiple columns are sorted on, manually set a column's SortGlyphDirection to properly indicate that the column is sorted.

The following example uses a DataTable and sets the default view's Sort property to sort on the second and third columns. The example also demonstrates setting the column's SortGlyphDirection. The example assumes that you have a DataGridView and a BindingSource component on your form:

DataTable dt = new DataTable();
dt.Columns.Add("C1", typeof(int));
dt.Columns.Add("C2", typeof(string));
dt.Columns.Add("C3", typeof(string));
dt.Rows.Add(1, "1", "Test1");
dt.Rows.Add(2, "2", "Test2");
dt.Rows.Add(2, "2", "Test1");
dt.Rows.Add(3, "3", "Test3");
dt.Rows.Add(4, "4", "Test4");
dt.Rows.Add(4, "4", "Test3");
DataView view = dt.DefaultView;
view.Sort = "C2 ASC, C3 ASC";
bindingSource.DataSource = view;
DataGridViewTextBoxColumn col0 = new DataGridViewTextBoxColumn();
col0.DataPropertyName = "C1";
dataGridView1.Columns.Add(col0);
col0.SortMode = DataGridViewColumnSortMode.Programmatic;
col0.HeaderCell.SortGlyphDirection = SortOrder.None;
DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
col1.DataPropertyName = "C2";
dataGridView1.Columns.Add(col1);
col1.SortMode = DataGridViewColumnSortMode.Programmatic;
col1.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
DataGridViewTextBoxColumn col2 = new DataGridViewTextBoxColumn();
col2.DataPropertyName = "C3";
dataGridView1.Columns.Add(col2);
col2.SortMode = DataGridViewColumnSortMode.Programmatic;
col2.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
Unbound DataGridView

To provide support for sorting on multiple columns you can handle the SortCompare event or call the Sort(IComparer) overload of the Sort method for greater sorting flexibility.

Custom Sorting Using the SortCompare Event

The following code example demonstrates custom sorting using a SortCompare event handler. The selected DataGridViewColumn is sorted and, if there are duplicate values in the column, the ID column is used to determine the final order.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
  private DataGridView dataGridView1 = new DataGridView();
  // Establish the main entry point for the application.
  [STAThreadAttribute()]
  static void Main()
  {
    Application.EnableVisualStyles();
    Application.Run(new Form1());
  }
  public Form1()
  {
    // Initialize the form.
    // This code can be replaced with designer generated code.
    dataGridView1.AllowUserToAddRows = false;
    dataGridView1.Dock = DockStyle.Fill;
    dataGridView1.SortCompare += new DataGridViewSortCompareEventHandler(
    this.dataGridView1_SortCompare);
    Controls.Add(this.dataGridView1);
    this.Text = "DataGridView.SortCompare demo";
    PopulateDataGridView();
  }
  // Replace this with your own population code.
  public void PopulateDataGridView()
  {
    // Add columns to the DataGridView.
    dataGridView1.ColumnCount = 3;
    // Set the properties of the DataGridView columns.
    dataGridView1.Columns[0].Name = "ID";
    dataGridView1.Columns[1].Name = "Name";
    dataGridView1.Columns[2].Name = "City";
    dataGridView1.Columns["ID"].HeaderText = "ID";
    dataGridView1.Columns["Name"].HeaderText = "Name";
    dataGridView1.Columns["City"].HeaderText = "City";
    // Add rows of data to the DataGridView.
    dataGridView1.Rows.Add(new string[] { "1", "Parker", "Seattle" });
    dataGridView1.Rows.Add(new string[] { "2", "Parker", "New York" });
    dataGridView1.Rows.Add(new string[] { "3", "Watson", "Seattle" });
    dataGridView1.Rows.Add(new string[] { "4", "Jameson", "New Jersey" });
    dataGridView1.Rows.Add(new string[] { "5", "Brock", "New York" });
    dataGridView1.Rows.Add(new string[] { "6", "Conner", "Portland" });
    // Autosize the columns.
    dataGridView1.AutoResizeColumns();
  }
  private void dataGridView1_SortCompare(object sender,
    DataGridViewSortCompareEventArgs e)
  {
    // Try to sort based on the cells in the current column.
    e.SortResult = System.String.Compare(
    e.CellValue1.ToString(), e.CellValue2.ToString());
    // If the cells are equal, sort based on the ID column.
    if (e.SortResult == 0 && e.Column.Name != "ID")
    {
      e.SortResult = System.String.Compare(
      dataGridView1.Rows[e.RowIndex1].Cells["ID"].Value.ToString(),
      dataGridView1.Rows[e.RowIndex2].Cells["ID"].Value.ToString());
    }
    e.Handled = true;
  }
}
Custom Sorting Using the IComparer Interface

The following code example demonstrates custom sorting using the Sort(IComparer) overload of the Sort method, which takes an implementation of the IComparer interface to perform a multiple-column sort.

using System;
using System.Drawing;
using System.Windows.Forms;
class Form1 : Form
{
  private DataGridView DataGridView1 = new DataGridView();
  private FlowLayoutPanel FlowLayoutPanel1 = new FlowLayoutPanel();
  private Button Button1 = new Button();
  private RadioButton RadioButton1 = new RadioButton();
  private RadioButton RadioButton2 = new RadioButton();
  // Establish the main entry point for the application.
  [STAThreadAttribute()]
  public static void Main()
  {
    Application.Run(new Form1());
  }
  public Form1()
  {
    // Initialize the form.
    // This code can be replaced with designer generated code.
    AutoSize = true;
    Text = "DataGridView IComparer sort demo";
    FlowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
    FlowLayoutPanel1.Location = new System.Drawing.Point(304, 0);
    FlowLayoutPanel1.AutoSize = true;
    FlowLayoutPanel1.Controls.Add(RadioButton1);
    FlowLayoutPanel1.Controls.Add(RadioButton2);
    FlowLayoutPanel1.Controls.Add(Button1);
    Button1.Text = "Sort";
    RadioButton1.Text = "Ascending";
    RadioButton2.Text = "Descending";
    RadioButton1.Checked = true;
    Controls.Add(FlowLayoutPanel1);
    Controls.Add(DataGridView1);
  }
  protected override void OnLoad(EventArgs e)
  {
    PopulateDataGridView();
    Button1.Click += new EventHandler(Button1_Click);
    base.OnLoad(e);
  }
  // Replace this with your own code to populate the DataGridView.
  private void PopulateDataGridView()
  {
    DataGridView1.Size = new Size(300, 300);
    // Add columns to the DataGridView.
    DataGridView1.ColumnCount = 2;
    // Set the properties of the DataGridView columns.
    DataGridView1.Columns[0].Name = "First";
    DataGridView1.Columns[1].Name = "Last";
    DataGridView1.Columns["First"].HeaderText = "First Name";
    DataGridView1.Columns["Last"].HeaderText = "Last Name";
    DataGridView1.Columns["First"].SortMode =
    DataGridViewColumnSortMode.Programmatic;
    DataGridView1.Columns["Last"].SortMode =
    DataGridViewColumnSortMode.Programmatic;
    // Add rows of data to the DataGridView.
    DataGridView1.Rows.Add(new string[] { "Peter", "Parker" });
    DataGridView1.Rows.Add(new string[] { "James", "Jameson" });
    DataGridView1.Rows.Add(new string[] { "May", "Parker" });
    DataGridView1.Rows.Add(new string[] { "Mary", "Watson" });
    DataGridView1.Rows.Add(new string[] { "Eddie", "Brock" });
  }
  private void Button1_Click(object sender, EventArgs e)
  {
    if (RadioButton1.Checked == true)
    {
      DataGridView1.Sort(new RowComparer(SortOrder.Ascending));
    }
    else if (RadioButton2.Checked == true)
    {
      DataGridView1.Sort(new RowComparer(SortOrder.Descending));
    }
  }
  private class RowComparer : System.Collections.IComparer
  {
  private static int sortOrderModifier = 1;
  public RowComparer(SortOrder sortOrder)
  {
    if (sortOrder == SortOrder.Descending)
    {
      sortOrderModifier = -1;
    }
    else if (sortOrder == SortOrder.Ascending)
    {
      sortOrderModifier = 1;
    }
  }
  public int Compare(object x, object y)
  {
    DataGridViewRow DataGridViewRow1 = (DataGridViewRow)x;
    DataGridViewRow DataGridViewRow2 = (DataGridViewRow)y;
    // Try to sort based on the Last Name column.
    int CompareResult = System.String.Compare(
    DataGridViewRow1.Cells[1].Value.ToString(),
    DataGridViewRow2.Cells[1].Value.ToString());
    // If the Last Names are equal, sort based on the First Name.
    if (CompareResult == 0)
    {
      CompareResult = System.String.Compare(
      DataGridViewRow1.Cells[0].Value.ToString(),
      DataGridViewRow2.Cells[0].Value.ToString());
    }
      return CompareResult * sortOrderModifier;
    }
  }
}


Page view counter