how to sort a datagridview by 2 columns

后端 未结 8 1345
北恋
北恋 2020-12-05 08:38

How do I sort a DataGridView by two columns (ascending)? I have two columns: day and status.

If I need to sort by one column, I do:

相关标签:
8条回答
  • 2020-12-05 09:02

    Here is a refinement on the IComparer class from @John Kurtz, which supports mutliple columns and sorting by numbers or dates.

        public static void SortOnMultipleColumns(DataGridView dgv, Dictionary<string /*Column Name*/, ColumnSortInfo> sortingColumns)
        {
            // Show the glyphs
            foreach (DataGridViewColumn col in dgv.Columns)
            {
                System.Windows.Forms.SortOrder sortOrder = System.Windows.Forms.SortOrder.None;
    
                foreach (var kvp in sortingColumns)
                {
                    if (kvp.Key == col.Name)
                    {
                        sortOrder = kvp.Value.SortOrder;
                        break;
                    }
                }
                col.HeaderCell.SortGlyphDirection = sortOrder;
            }
    
            // Sort the grid
            MultiColumnCompararor multiColumnCompararor = new MultiColumnCompararor(sortingColumns);
            dgv.Sort(multiColumnCompararor);
        }
    
        public class ColumnSortInfo
        {
            public enum ValueConversion { ToString, ToNumber, ToDate}
            public ColumnSortInfo(System.Windows.Forms.SortOrder sortOrder, ValueConversion valueConversion = ValueConversion.ToString)
            {
                SortOrder = sortOrder;
                MyValueConversion = valueConversion;
                SortOrderMultiplier = (SortOrder == SortOrder.Ascending) ? 1 : -1;
            }
            public System.Windows.Forms.SortOrder SortOrder { get; set; }
            public int SortOrderMultiplier { get; }
            public ValueConversion MyValueConversion { get; set; }
    
            public static double StringToDouble(string sVal)
            {
                if (Double.TryParse(sVal, out double dVal))
                {
                    return dVal;
                }
                return 0;
            }
            public static DateTime StringToDateTime(string sVal)
            {
                if (DateTime.TryParse(sVal, out DateTime dt))
                {
                    return dt;
                }
                return DateTime.MinValue;
            }
        }
        private class MultiColumnCompararor : System.Collections.IComparer
        {
    
            IDictionary<string /*Column Name*/, ColumnSortInfo> _sortingColumns;
    
            public MultiColumnCompararor(IDictionary<string /*Column Name*/, ColumnSortInfo> sortingColumns)
            {
                _sortingColumns = sortingColumns;
            }
    
            public int Compare(object x, object y)
            {
                try
                {
                    DataGridViewRow r1 = (DataGridViewRow)x;
                    DataGridViewRow r2 = (DataGridViewRow)y;
    
                    foreach (var kvp in _sortingColumns)
                    {
                        string colName = kvp.Key;
                        ColumnSortInfo csi = kvp.Value;
    
                        string sVal1 = r1.Cells[colName].Value?.ToString().Trim()??"";
                        string sVal2 = r2.Cells[colName].Value?.ToString().Trim()??"";
    
                        int iCompareResult = 0;
    
                        switch (csi.MyValueConversion)
                        {
                            case ColumnSortInfo.ValueConversion.ToString:
                                iCompareResult = String.Compare(sVal1, sVal2);
                                break;
                            case ColumnSortInfo.ValueConversion.ToNumber:
                                double d1 = ColumnSortInfo.StringToDouble(sVal1);
                                double d2 = ColumnSortInfo.StringToDouble(sVal2);
                                iCompareResult = ((d1 == d2) ? 0 : ((d1 > d2) ? 1 : -1));
                                break;
                            case ColumnSortInfo.ValueConversion.ToDate:
                                DateTime dt1 = ColumnSortInfo.StringToDateTime(sVal1);
                                DateTime dt2 = ColumnSortInfo.StringToDateTime(sVal2);
                                iCompareResult = ((dt1 == dt2) ? 0 : ((dt1 > dt2) ? 1 : -1));
                                break;
                            default:
                                break;
                        }
    
                        iCompareResult = csi.SortOrderMultiplier * iCompareResult;
    
                        if (iCompareResult != 0) { return iCompareResult; }
                    }
                    return 0;
                }
                catch (Exception ex)
                {
                    return 0;
                }
            }
        }
    

    Usage:

            Dictionary<String, ColumnSortInfo> sortingColumns = new Dictionary<String, ColumnSortInfo>
                            { {"policyNumber", new ColumnSortInfo(System.Windows.Forms.SortOrder.Ascending)},
                              {"MessageId", new ColumnSortInfo(System.Windows.Forms.SortOrder.Descending, ColumnSortInfo.ValueConversion.ToNumber)},
                              {"CreationDate", new ColumnSortInfo(System.Windows.Forms.SortOrder.Ascending, ColumnSortInfo.ValueConversion.ToDate)}};
    
            CsUtils.SortOnMultipleColumns(dgv, sortingColumns);
    
    0 讨论(0)
  • 2020-12-05 09:05

    I use this solution when working with bound data. This works for our users, and displays the current sort criteria. All sorts are only in ascending order.

    Add a CheckBox, a TextBox, a ColumnHeaderMouseClick event, and code as shown. The CheckBox will toggle the TextBox's visibility, and clicking on any column header will add the sort criteria to the TextBox. To clear the TextBox, just double click in it.

            private void FooDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
            {
                if(chkMultiSort.Checked == true)
                {
                    string columnHeader = FooDataGridView.Columns[e.ColumnIndex].DataPropertyName;
                    txtMultiSort.Text += (columnHeader + ", ");
                    try
                    {
                        FooBindingSource.Sort = txtMultiSort.Text.Remove(txtMultiSort.Text.Length - 2);
                    }
                    catch
                    {
                        MessageBox.Show("Invalid Sort Data", "Information", MessageBoxButtons.OK, MessageBoxIcon.None);
                        txtMultiSort.Text = String.Empty;
                    }
                }
    
            }
    
            private void ChkMultiSort_CheckedChanged(object sender, EventArgs e)
            {
                if(chkMultiSort.Checked == true)
                {
                    txtMultiSort.Visible = true;
                }
                else
                {
                    txtMultiSort.Visible = false;
                    txtMultiSort.Text = String.Empty;
                }
            }
    
            private void TxtMultiSort_DoubleClick(object sender, EventArgs e)
            {
                txtMultiSort.Text = String.Empty;
            }
    
    
    0 讨论(0)
提交回复
热议问题