C #: пользовательский вид DataGridView - PullRequest
19 голосов
/ 12 января 2009

Мне нужно отсортировать DataGridView с естественной сортировкой (как в Проводнике), чтобы числа и текст (в одном столбце) сортировались естественным образом, а не в алфавитном порядке (чтобы «место 3» предшествовало «месту 20» и т. Д. .). У меня есть DataGridView, где я установил DataView в качестве источника данных. DataView содержит DataTable, который создается с некоторыми значениями из базы данных. Типы столбцов являются строковыми. У меня есть IComparer, который делает то, что должен, но я не могу понять, как его использовать, потому что я не могу узнать, как выполнить сортировку. Событие DataGridView.SortCompare, которое было бы perfect , не работает, поскольку оно связано с данными. DataView.Sort, принимает только строки с именами столбцов и порядками сортировки.

Очень раздражает. Пытался прочитать связанные с этим вопросы здесь, в StackOverflow, и искал в Google много-много, но я не могу найти много об этом. Единственное, что я действительно нахожу, - это использование метода сортировки (строки) представления данных, который не будет работать, поскольку он сортирует по алфавиту.

Кто-нибудь знает, как это сделать без особых проблем? Должно быть, другие, кроме меня, борются с этим? Я действительно не хочу повторно реализовывать все классы datagridview или dataview, просто чтобы получить пользовательскую сортировку ...

Обновление : Если кому-то интересно, я все еще ищу хороший ответ на эту проблему. Хотя в то же время я закончил тем, что создал свой собственный простой класс таблиц, а затем вручную добавил его в таблицу данных. Переопределение метода SortCompare. Немного раздражает, но не слишком сложно, так как мне нужно только показать значения (без редактирования или чего-либо еще) и, следовательно, можно преобразовать все в строки.

Ответы [ 5 ]

5 голосов
/ 12 января 2009

Взгляните на эту страницу MSDN и эту запись в блоге . В принципе, вам необходимо настроить сортировку в источнике данных (будь то ObjectDataSource или SqlDataSource), а не в GridView.

Насколько я могу судить, класс DataView не поддерживает ничего, кроме простой сортировки по возрастанию / убыванию. Не видя код, в который вы загружаете и связываете данные, трудно дать конкретную рекомендацию, но вы можете либо:

  1. Загрузите ваши данные в список вместо DataTable, вызовите метод Sort, передав его в свой метод сравнения, а затем привяжите к этому списку.
  2. Создайте ObjectDataSource в своем коде aspx, который получает данные непосредственно из класса, и настройте этот ObjectDataSource для использования вашего IComparer.
2 голосов
/ 04 января 2012

Этот код должен работать. Это похоже на ListViewItemSorter ListView. Использование IComparer.

Для использования:

private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    MyDataGridHelper.DataGridSort(dgv, e.ColumnIndex);
}

MyDataGridHelper.cs:

public class MyDataGridHelper
{
    public static void DataGridSort(DataGridView dgv, int column)
    {
        DataGridViewCustomSorter dgvSorter = null;
        if (dgv.Tag == null || !(dgv.Tag is IComparer))
        {
            dgvSorter = new DataGridViewCustomSorter(dgv);
            dgv.Tag = dgvSorter;
        }
        else
        {
            dgvSorter = (DataGridViewCustomSorter)dgv.Tag;
        }
        dgvSorter.SortColumn = column;
        dgv.Sort(dgvSorter);
    }

    private class DataGridViewCustomSorter : IComparer
    {
        private int ColumnIndex;
        private SortOrder OrderOfSort;
        private DataGridView myDataGridView;
        private TypeCode mySortTypeCode;

        public DataGridViewCustomSorter(DataGridView dgv)
        {
            myDataGridView = dgv;
            mySortTypeCode = Type.GetTypeCode(Type.GetType("System.String"));
            ColumnIndex = 0;
            OrderOfSort = SortOrder.None;
        }

        public int Compare(object x, object y)
        {
            int result;
            DataGridViewRow dgvX, dgvY;

            dgvX = (DataGridViewRow)x;
            dgvY = (DataGridViewRow)y;
            string sx = dgvX.Cells[ColumnIndex].Value.ToString();
            string sy = dgvY.Cells[ColumnIndex].Value.ToString();

            //null handling
            if (sx == String.Empty && sy == String.Empty)
                result = 0;
            else if (sx == String.Empty && sy != String.Empty)
                result = -1;
            else if (sx != String.Empty && sy == String.Empty)
                result = 1;
            else
            {
                switch (mySortTypeCode)
                {
                    case TypeCode.Decimal:
                        Decimal nx = Convert.ToDecimal(sx);
                        Decimal ny = Convert.ToDecimal(sy);
                        result = nx.CompareTo(ny);
                        break;
                    case TypeCode.DateTime:
                        DateTime dx = Convert.ToDateTime(sx);
                        DateTime dy = Convert.ToDateTime(sy);
                        result = dx.CompareTo(dy);
                        break;
                    case TypeCode.String:
                        result = (new CaseInsensitiveComparer()).Compare(sx, sy);
                        break;
                    default:
                        result = (new CaseInsensitiveComparer()).Compare(sx, sy);
                        break;
                }
            }
            if (OrderOfSort == SortOrder.Descending)
                result = (-result);

            return result;
        }

        public int SortColumn
        {
            set
            {
                if (ColumnIndex == value)
                {
                    OrderOfSort = (OrderOfSort == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending);
                }
                ColumnIndex = value;
                try
                {
                    mySortTypeCode = Type.GetTypeCode(Type.GetType((myDataGridView.Columns[ColumnIndex]).Tag.ToString()));
                }
                catch
                {
                    mySortTypeCode = TypeCode.String;
                }
            }
            get { return ColumnIndex; }
        }

        public SortOrder Order
        {
            set { OrderOfSort = value; }
            get { return OrderOfSort; }
        }
    } //end class DataGridViewCustomSorter
} //end class MyDataGridHelper
0 голосов
/ 16 марта 2012

Вы можете переместить логику сортировки в запрос к вашей базе данных и вернуть ей дополнительный столбец с правильным порядком сортировки.

Тогда (в соответствии с ответом @True C Sharp) у вас может быть скрытый столбец, содержащий это значение, и сортировать его по этому, а не по столбцу отображения.

Предполагается, что логика для определения порядка сортировки может быть выполнена в SQL. Это может не сработать, если алгоритм определения порядка сортировки сложен.

0 голосов
/ 17 ноября 2010

Здесь есть какое-то решение " Выборочная сортировка с использованием события SortCompare "и" Выборочная сортировка с использованием интерфейса IComparer":

http://msdn.microsoft.com/en-us/library/ms171608.aspx

0 голосов
/ 12 января 2009

Вы можете создать 2 скрытых столбца. Присвойте текстовую часть первому скрытому столбцу, а номерную часть - второму скрытому столбцу. Теперь сортируйте по этим скрытым столбцам (альфа-сортировка для 1-го столбца и числовая сортировка для 2-го столбца).

Таким образом, вы можете сохранить исходный столбец для отображения и иметь 2 скрытых столбца для сортировки.

...