how to sort a datagridview by 2 columns

后端 未结 8 1373
北恋
北恋 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 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 _sortingColumns;
    
            public MultiColumnCompararor(IDictionary 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 sortingColumns = new Dictionary
                            { {"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);
    

提交回复
热议问题