Введение в ADO.NET. Источник данных - XML-файл. Отображение данных связанной таблицы, страница 16

      foreach (// Здесь ваш код По всем колонкам col активной grid)

      {

        if (col.HeaderText == "ID")

           continue;

        object data = row[col.HeaderText];

        string val = data.ToString();

        if (col.ValueType == typeof(DateTime) && data != DBNull.Value)

           val = ((DateTime)data).ToShortDateString();

        item.SubItems.Add(val);

      }

      list.Items.Add(item);

    }

    list.Width = listWidth + 20;

    list.Height = 100;

    ShowSearchResults(list, text);

  }

Проверка на  DBNull существенна. Проверку типа данных текущей колонки можно произвести и другим способом:

if (col.Name == "Date" && data != DBNull.Value)

Остался нереализованным лишь один метод — GetSelectCriteia. Он должен корректировать синтаксис SQL-запроса, в зависимости от типа данных активной колонки таблицы. Дело в том, что при выполнении запроса (метода Select) шаблон вида LIKE работает только для текстовых колонок таблицы. Для остальных типов колонок мы будем искать точное совпадение данных. Колонка даты экзамена также вносит специфику в формат строки запроса. Так как синтаксис SQL-запроса для числовых и текстовых колонок отличается, то нам приходится производить ветвление алгоритма в зависимости от активной колонки таблицы, определяемой активной ячейкой DataGridView.

  string GetSelectCriteia()

  {

    DataColumn dc = activeTable.Columns[activeCell.ColumnIndex];

    string colName = dc.ColumnName;

    if (colName != searchColumnName)

      searchColumnName = colName;

    Type type = dc.DataType;

    string sel = "";

    switch (type.Name)

    {

      case "String": sel = " LIKE '" + findWhat + "*'"; break;

      case "Decimal":    case "Byte":     case "SByte":

      case "Int16":      case "UInt16":   case "Int64":

      case "UInt64":     case "UInt32":

      case "Int32": sel = "=" + findWhat; break;

      case "DateTime":

        DateTime dt;

        bool ok = DateTime.TryParse(findWhat, out dt);

        if (ok)

           sel = " = #" + dt.ToShortDateString() + "#"; // ToString ???

        else

           return null;

        break;

    }

    return sel;

  }

Код метода FindNext остается тем же, если вы своевременно произвели в нем замену studsGrid на activeGrid. На следующем рисунке вы видите результаты поиска четверок в вычисляемой колонке среднего балла. Повторное нажатие кнопки btnFindList не должно вызывать повторного создания (а, следовательно, и перерисовки) формы formFind. При перемещении фокуса в колонку оценок (таблицы экзаменов) поиск должен обновить содержимое списка (заново создать форму formFind) и переключиться на отслеживание позиций в колонке Mark.

Колонка Date таблицы экзаменов преподносит сюрпризы при выполнении метода ShowAll. Просмотрите значения этих полей в XML-файле. Частью даты (объекта DataTime) является время: 2006-01-20T00:00:00+03:00. Символы +03:00, как вы догадались, являются региональным сдвигом.

При выполнении метода Select (то есть, SQL-запроса по дате) наличие времени мешает. Причина в том, что мы вынуждены искать точное совпадение, так как шаблон критерия отбора вида LIKE работает только для текстовых колонок таблицы. Нам, безусловно, не хочется вводить дату в таком сложном формате, да еще с учетом регионального времени. Если в XML-файле вручную убрать время (оставив только дату) и заново прочесть файл, то алгоритм фильтрации по дате работает правильно. Частично эта проблема решается и без корректировки данных. Они все равно восстановятся (добавится время) при следующей записи в файл. Вместо метода ToShortDateString, который я (в целях экономии) использовал при формировании критерия отбора, надо просто использовать метод ToString.

Обрамление даты в виде #2006-01-20T00:00:00+03:00# требует синтаксис SQL. Я нашел этот трюк в книге David Sceppa Microsoft ADO.NET (сам я с форматами SQL почти не знаком).