DataGridView Пользовательская сортировка - PullRequest
4 голосов
/ 18 августа 2011

У меня есть DataGridView с 6 столбцами.

Пример:

column1    column2    column3    column4    column5    column6
J6         RES-0112G  123.123    456.456    180        1111
FID2       FIDUCIAL   5.123     -50.005     90         FIDUCIAL
R100       RES-0113G  1.1       -123.123    90         1111
C12        CAP-1234H -99.99     -987.123    45         2222
Q1         CAP-1234Z -99.99     -987.123    45         4444
J3         RES-0112G  123.123    999.999    0          1111
FID1       FIDUCIAL   23.123     23.123     0          FIDUCIAL
F1         CAP-1234  -88.99     -555.111    45         DDDD
C11        CAP-1234Z -123.99    -123.123    270        abc2222

И я бы хотел отсортировать его в особом порядке. Допустим, я хочу отсортировать его по последнему значению (столбец 6) в следующей последовательности:

FIDUCIAL, 1111, 2222, DDDD, 4444

И затем отсортировать его по 2-му столбцу в алфавитном порядке. (ЗАМЕТЬТЕ abc2222 сортирует по "2222", а не "abc") .

Таким образом, обновленный DataGridView будет выглядеть следующим образом: (Для FIDUCIALS я бы хотел отсортировать по столбцу 1 вместо столбца 2)

column1    column2    column3    column4    column5    column6
FID1       FIDUCIAL   23.123     23.123     0          FIDUCIAL
FID2       FIDUCIAL   5.123     -50.005     90         FIDUCIAL
J6         RES-0112G  123.123    456.456    180        1111
J3         RES-0112G  123.123    999.999    0          1111
R100       RES-0113G  1.1       -123.123    90         1111
C11        CAP-1234C -123.99    -123.123    270        abc2222
C12        CAP-1234H -99.99     -987.123    45         2222
F1         CAP-1234  -88.99     -555.111    45         DDDD
Q1         CAP-1234Z -99.99     -987.123    45         4444

Кто-нибудь знает, как правильно это отсортировать? Я использую SortableBindingList<>

Ответы [ 3 ]

3 голосов
/ 21 августа 2011

Я создал пример кода, чтобы показать вам саму технику. Надеюсь, вам не составит труда адаптироваться к вашим потребностям. Основная идея заключается в том, что вы группируете по нужному столбцу, а затем применяете пользовательскую сортировку внутри группы. Я не понял алгоритм сортировки для column6, поэтому я сделал простую сортировку на основе ваших примеров данных. Надеюсь, это поможет!

class Program
{
    public class Row
    {
        public string Column1 { get; set; }
        public string Column2 { get; set; }
        public string Column3 { get; set; }
        public string Column4 { get; set; }
        public string Column5 { get; set; }
        public string Column6 { get; set; }
    }

    static void Main(string[] args)
    {
        var grid = new []
                       {
                           new Row { Column1 = "J6", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "456.456", Column5 = "180", Column6 = "1111"},
                           new Row { Column1 = "FID2", Column2 = "FIDUCIAL", Column3 = "5.123", Column4 = "-50.005", Column5 = "90", Column6 = "FIDUCIAL"},
                           new Row { Column1 = "R100", Column2 = "RES-0113G", Column3 = "1.1", Column4 = "-123.123", Column5 = "90", Column6 = "1111"},
                           new Row { Column1 = "C12", Column2 = "CAP-1234H", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "2222"},
                           new Row { Column1 = "Q1", Column2 = "CAP-1234Z", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "4444"},
                           new Row { Column1 = "J3", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "999.999", Column5 = "0", Column6 = "1111"},
                           new Row { Column1 = "FID1", Column2 = "FIDUCIAL", Column3 = "23.123", Column4 = "23.123", Column5 = "0", Column6 = "FIDUCIAL"},
                           new Row { Column1 = "F1", Column2 = "CAP-1234", Column3 = "-88.99", Column4 = "-555.111", Column5 = "45", Column6 = "DDDD"},
                           new Row { Column1 = "C11", Column2 = "CAP-1234C", Column3 = "-123.99", Column4 = "-123.123", Column5 = "270", Column6 = "abc2222"}
                       };

        var result = grid.
            GroupBy(r => GetSortValue(r.Column6)).
            OrderBy(g => g.Key, new Column6Comparer()).
            SelectMany(g => g.OrderBy(r => r, new RowComparer()));

        foreach (var row in result)
        {
            Console.WriteLine("{0,-6}{1,-13}{2,-10}{3,-12}{4,-6}{5,-10}", row.Column1, row.Column2, row.Column3, row.Column4, row.Column5, row.Column6);
        }
    }

    private static string GetSortValue(string source)
    {
        Match match = new Regex(@"[\d]+").Match(source);
        return match.Success ? match.Value : source;
    }

    private class Column6Comparer : IComparer<string>
    {
        private Dictionary<string, int> ValueToOrder { get; set; } 
        public Column6Comparer()
        {
            ValueToOrder = new Dictionary<string, int>();
            ValueToOrder["FIDUCIAL"] = 0;
            ValueToOrder["1111"] = 1;
            ValueToOrder["2222"] = 2;
            ValueToOrder["DDDD"] = 3;
            ValueToOrder["4444"] = 4;
        }

        public int Compare(string x, string y)
        {
            return ValueToOrder[GetSortValue(x)].CompareTo(ValueToOrder[GetSortValue(y)]);
        }

    }

    private class RowComparer : IComparer<Row>
    {
        public int Compare(Row x, Row y)
        {
            if (x.Column2 == "FIDUCIAL" && y.Column2 == "FIDUCIAL")
            {
                return x.Column1.CompareTo(y.Column1);
            }

            if (x.Column2 == "FIDUCIAL" || y.Column2 == "FIDUCIAL")
            {
                return x.Column2 == "FIDUCIAL" ? 0 : 1;
            }

            return x.Column2.Substring(4).CompareTo(y.Column2.Substring(4));
        }
    }
}
1 голос
/ 27 августа 2011

Вот более общий подход, который можно использовать для нескольких случаев, подобных этому,

public class Row
    {
        public string Column1 { get; set; }
        public string Column2 { get; set; }
        public string Column3 { get; set; }
        public string Column4 { get; set; }
        public string Column5 { get; set; }
        public string Column6 { get; set; }
    }

public interface IComplexSorter<T> : IComparer<T>
    {
    }

public class ComplexSorter<T> : IComplexSorter<T>
    {
        private IList<IComplexSorter<T>> _rowSorters;

        public ComplexSorter()
        {
            _rowSorters = new ReadOnlyCollectionBuilder<IComplexSorter<T>>();
        }

        public int Compare(T x, T y)
        {
            foreach (var sorter in Sorters)
            {
                int value = sorter.Compare(x, y);
                if (value != 0)
                    return value;
            }
            return 0;
        }

        public IList<IComplexSorter<T>> Sorters
        {
            get { return _rowSorters; }
        }
    }

public class RowColumn1Sorter : IComplexSorter<Row>
    {
        public int Compare(Row x, Row y)
        {
            if (x.Column6 == "FIDUCIAL" && y.Column6 == "FIDUCIAL")
                return x.Column1.CompareTo(y.Column1);

            if (x.Column6 == "FIDUCIAL" || y.Column6 == "FIDUCIAL")
                return x.Column6 == "FIDUCIAL" ? 0 : 1;

            return 0;
        }
    }

public class RowColumn2Sorter : IComplexSorter<Row>
    {
        public int Compare(Row x, Row y)
        {
            return x.Column2.Substring(4).CompareTo(y.Column2.Substring(4));
        }
    }

public class RowColumn6Sorter : IComplexSorter<Row>
    {
        private static IList<string> SortOrder;

        public RowColumn6Sorter()
        {
            SortOrder = new string[] { "FIDUCIAL", "1111", "2222", "DDDD", "4444" }.ToList();
        }

        public int Compare(Row x, Row y)
        {
            string xSortValue = SortOrder.Contains(x.Column6) ? x.Column6 : ExtractNumeric(x.Column6);
            string ySortValue = SortOrder.Contains(y.Column6) ? y.Column6 : ExtractNumeric(y.Column6);
            int xKey = SortOrder.IndexOf(xSortValue);
            int yKey = SortOrder.IndexOf(ySortValue);
            xKey = xKey == -1 ? SortOrder.Count:xKey;
            yKey = yKey == -1 ? SortOrder.Count:yKey;
            return xKey - yKey;
        }

        private string ExtractNumeric(String value)
        {
            Match match = new Regex(@"[\d]+").Match(value);
            return match.Success ? match.Value : value;
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            var data = new[]
            {
                new Row { Column1 = "J6", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "456.456", Column5 = "180", Column6 = "1111"},
                new Row { Column1 = "FID2", Column2 = "FIDUCIAL", Column3 = "5.123", Column4 = "-50.005", Column5 = "90", Column6 = "FIDUCIAL"},
                new Row { Column1 = "R100", Column2 = "RES-0113G", Column3 = "1.1", Column4 = "-123.123", Column5 = "90", Column6 = "1111"},
                new Row { Column1 = "C12", Column2 = "CAP-1234H", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "2222"},
                new Row { Column1 = "Q1", Column2 = "CAP-1234Z", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "4444"},
                new Row { Column1 = "J3", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "999.999", Column5 = "0", Column6 = "1111"},
                new Row { Column1 = "FID1", Column2 = "FIDUCIAL", Column3 = "23.123", Column4 = "23.123", Column5 = "0", Column6 = "FIDUCIAL"},
                new Row { Column1 = "F1", Column2 = "CAP-1234", Column3 = "-88.99", Column4 = "-555.111", Column5 = "45", Column6 = "DDDD"},
                new Row { Column1 = "C11", Column2 = "CAP-1234C", Column3 = "-123.99", Column4 = "-123.123", Column5 = "270", Column6 = "abc2222"}
            }.ToList();

            ComplexSorter<Row> rowSorter = new ComplexSorter<Row>();
            rowSorter.Sorters.Add(new RowColumn6Sorter());
            rowSorter.Sorters.Add(new RowColumn1Sorter());
            rowSorter.Sorters.Add(new RowColumn2Sorter());

            data.Sort(rowSorter);

            foreach (var row in data)
            {
                Console.WriteLine("{0,-6}{1,-13}{2,-10}{3,-12}{4,-6}{5,-10}", row.Column1, row.Column2, row.Column3, row.Column4, row.Column5, row.Column6);
            }
            Console.ReadKey();
        }
    }
1 голос
/ 25 августа 2011

SortableBindingList работает против вас, потому что он был разработан для сортировки данных, используя значения одного свойства (столбца). Вам придется отсортировать данные перед добавлением в список привязок и отключить сортировку. Вы можете отсортировать данные с помощью такого компаратора.

public class RowComparer : IComparer<Row>
    {
    private List<string> myOrder = new List<string>(new string[] { "FIDUCIAL", "1111", "2222", "DDDD", "4444" });

    private int primaryOrder(Row x)
        {
        int index = myOrder.FindIndex(v => x.Column6.Contains(v));
        return (index >= 0) ? index : myOrder.Count;
        }

    public int Compare(Row x, Row y)
        {
        int result = primaryOrder(x).CompareTo(primaryOrder(y));
        if (result != 0)
            return result;

        return x.Column2.CompareTo(y.Column2);
        }
    }

Вот способ написать Comparer, который еще более гибок:

    public class CustomComparer : IComparer<Row>
        {
        Predicate<Row>[] myOrder = new Predicate<Row>[]
        {
            (row) => row.Column6 == "FIDUCIAL",
            (row) => row.Column6.Contains("1111") && !row.Column3.Contains("unwanted"),
            (row) => row.Column6.Contains("2222"),
            (row) => row.Column6.StartsWith("DDDD"),
            (row) => row.Column6 == "4444",
        };

        private int primaryOrder(Row row)
            {
            for (int i = 0; i < myOrder.Length; i++)
                {
                if (myOrder[i](row))
                    return i;
                }
            return myOrder.Length;
            }

        public int Compare(Row x, Row y)
            {
            int result = primaryOrder(x).CompareTo(primaryOrder(y));
            if (result != 0)
                return result;

            return x.Column2.CompareTo(y.Column2);
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...