Сортировка DataGridView с нулями в столбце DateTime

У меня есть элемент управления DataGridView в приложении Windows Forms. Есть четыре столбца со строковыми данными и три с данными DateTime. Я добавляю строки программно, используя метод Rows.Add (). Для всех столбцов SortMode установлено значение Automatic. Щелчок по заголовкам столбцов для сортировки просто работает, за исключением одного столбца DateTime, в котором есть несколько значений NULL. Когда пользователь щелкает заголовок этого столбца, возникает исключение ArgumentException: объект должен иметь тип DateTime.

Я знаю трудный способ обойти это: установка для всех SortModes значения NotSortable, обработка события ColumnHeaderMouseClick и сортировка всего этого вручную. Я ищу легкий путь.

Есть ли свойство или что-то, что я могу установить, или какой-либо другой относительно простой способ разрешить сортировку этого столбца с нулями в нем?


person John M Gant    schedule 15.05.2009    source источник
comment
Если DataGridView имеет значение DataBound..SortCompare не работает. Есть ли другая альтернатива этому?   -  person Vijay Balkawade    schedule 06.12.2011


Ответы (5)


Простое решение - добавить функцию «tonull», которую вы запускаете для e.cellvalue1 и 2 каждый раз, когда выполняется сравнение. Если значение равно "", то значение ячейки будет изменено на 01.01.1001, если вы хотите, чтобы нулевые значения отображались первыми при сортировке, или 01.01.2001, или что-то смехотворно высокое, если вы хотите, чтобы они отображались последними сорт.

Private Sub dgvTable_SortCompare(ByVal sender As Object, ByVal e As DataGridViewSortCompareEventArgs) Handles dgvTable.SortCompare

    If e.Column.Index = 4 Then

        e.SortResult = System.DateTime.Compare(todatenull(e.CellValue1), todatenull(e.CellValue2))

    End If

    e.Handled = True
End Sub


Function todatenull(ByVal cellvalue)
    If cellvalue = "" Then
        Return "01/01/1001"
    Else
        Return cellvalue
    End If
End Function
person Tom Callaghan    schedule 02.03.2011

Вот решение, которое я придумал. DataGridView вызывает событие SortCompare, которое можно использовать для ввода настраиваемой сортировки. Я обрабатываю это событие и делаю нулевые значения выше, чем ненулевые значения (вы можете так же легко сделать нулевые значения ниже ненулевых). Вот код VB. Я предполагаю, что каждое значение ячейки является IComparable (в противном случае оно будет обрабатываться обычной логикой обработки ошибок).

Try
    If e.CellValue1 Is Nothing OrElse e.CellValue1.Equals(DBNull.Value) Then
        If e.CellValue2 Is Nothing OrElse e.CellValue2.Equals(DBNull.Value) Then
            e.SortResult = 0
        Else
            e.SortResult = 1
        End If
    Else
        If e.CellValue2 Is Nothing OrElse e.CellValue2.Equals(DBNull.Value) Then
            e.SortResult = -1
        Else
            e.SortResult = DirectCast(e.CellValue1, IComparable).CompareTo(DirectCast(e.CellValue2, IComparable))
        End If
    End If
    e.Handled = True
Catch ex As Exception
    HandleError("Error sorting result grid values", ex)
    Close()
End Try

Если у кого-то есть какие-либо улучшения, пожалуйста, публикуйте их.

person John M Gant    schedule 18.05.2009
comment
См. Мой обновленный ответ. Если то, что вы опубликовали, решает вашу проблему, круто. Но мне интересно узнать, работает ли мое предложение и для вас. - person Kyle Gagnet; 18.05.2009
comment
Если DataGridView имеет значение DataBound..SortCompare не работает. Есть ли другая альтернатива этому? - person Vijay Balkawade; 06.12.2011

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

Если это нехорошо - как насчет создания собственного DataGridView, точно такого же, как и встроенный (с использованием наследования), НО с переопределением метода сортировки для игнорирования нулей?

person JohnIdol    schedule 15.05.2009
comment
Вы правы, это не DataBound. Это хорошее предложение, но я бы предпочел оставить на дисплее нули, если это возможно. Я сохраню это как план Б. - person John M Gant; 16.05.2009
comment
Я могу попробовать. Это, вероятно, не меньше работы, чем ручная обработка сортировки, но, по крайней мере, было бы интереснее. - person John M Gant; 16.05.2009
comment
это, вероятно, более чистый подход, чем обработка сортировки из некоторого клиентского объекта (сам класс WinForm был бы хорошим кандидатом для такого рода искажений) - person JohnIdol; 16.05.2009

Обновленный ответ: посмотрев ваш опубликованный ответ, я вижу, что вы проверяете DBNull.Value в ячейках. Это может быть источником вашей проблемы, поскольку DBNull.Value не может быть приведен к DateTime. Если вы добавляете строки программно, попробуйте заменить DBNull.Value значением null (Nothing).


Исходный ответ: попробуйте сделать это для каждого столбца, содержащего данные DateTime, желательно до загрузки каких-либо данных:

myDateTimeColumn.ValueType = GetType(DateTime)

Согласно MSDN, ValueType свойство «используется при фильтрации или сортировке столбцов по содержимому их ячеек». Поэтому я бы обязательно установил его для любого столбца, в котором разрешена сортировка.

С этим набором свойств сетка может быть отсортирована по столбцу, который имеет значения NULL, что приведет к принудительному преобразованию вставленных / обновленных ячеек в DateTime.

person Kyle Gagnet    schedule 16.05.2009
comment
Спасибо за сообщение. Я определяю столбцы в конструкторе, а не программно, и у меня есть несколько столбцов. Интересно, может ли какое-либо из этих двух различий объяснять разные результаты. - person John M Gant; 18.05.2009

Просто чтобы добавить код к этому вопросу ... Я сделал следующее, чтобы сортировка работала правильно для DateTime (и других нестроковых типов) при наличии нулей:

public MyFormCTor() {
    ...
    m_dataGridView.SortCompare += MySortCompare;
    ...
}

...

static void MySortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
    if (e.CellValue1 == e.CellValue2)
    {
        e.SortResult = 0;
        return;
    }

    if (e.CellValue1 == null)
    {
        e.SortResult = -1;
        return;
    }

    if (e.CellValue2 == null)
    {
        e.SortResult = 1;
        return;
    }

    e.SortResult = ((IComparable)e.CellValue1).CompareTo(e.CellValue2);
}
person liwp    schedule 21.09.2010