lab_wpf_data_csv.md 5.6 KB

Получение данных из внешних источников. CSV.

  1. Для начала создаём файл с данными для импорта. Я продолжаю тему кошек, вы реализуете свою предметную область:

    Мы должны уметь работать с разными типами данных, поэтому я добавил в исходные данные тип Date (дата прививки). Формат даты имеет множество разных форматов, но при экспорте обычно используют SQL формат (yyyy-mm-dd)

    age,breed,color,name,photo,dateOfLastVaccination
    1,"Дворняжка","Белый","Ириска",,2024-04-29
    2,"Шотландская вислоухая","Коричневый","Изи",,2020-01-31
    3,"Сиамский","Цветной","Макс",,2022-05-10
    
    • в первой строке названия полей, соответствующие модели данных
    • разделитель запятая
    • строковые литералы (текст, в котором могут встретиться спец.символы, а лучше все текстовые поля) заключаем в двойные кавычки
    • для отсутствующих полей (у меня photo) оставляем пустую строку

    Файл сохраняем в подкаталог bin/debug/net8.0-windows вашего проекта - туда, где создается исполняемый (.exe) файл (название зависит от версии .NET и платформы).

  2. Правим модель (у нас добавилось свойство "Дата последней прививки")

    public class Cat
    {
        public string name { get; set; }
        public int age{ get; set; }
        public string color { get; set; }
        // порода
        public string breed { get; set; }
        public string photo { get; set; }
        // новое свойство
        public DateOnly dateOfLastVaccination { get; set; }  
    }
    
  3. Загружаем данные из файла в класс поставщика данных

    Тут есть два варианта: либо каждый раз загружать данные при вызове метода getCats, либо загрузить один раз при создании экземпляра класса (в конструкторе). Оба варианта имеют право на жизнь: первый имеет смысл применять, если данные часто меняются, второй, если данные статичны. Я реализую второй вариант.

    Вспоминаем материалы лекции про типы данных и создаём для работы с CSV файлами класс CSVDataProvider, реализующий интерфейс IDataProvider:

    • Создаём приватную переменную для хранения загруженного списка и считываем данные в конструкторе:

      Библиотека CsvHelper достаточно "умная" и преобразует строку в дату автоматически

      Но в то же время они и "слишком умная", если данные не соответсвуют модели (не хватает полей) или типу (например, в дате нет времени), то запись игнорируется

      public class SCVDataProvider : IDataProvider
      {
          private List<Cat> catList;
      
          // конструктор класса
          public CSVDataProvider()
          {
              using (var reader = new StreamReader("./cat.csv")) {
                  using (var csv = new CsvReader(
                      reader, 
                      CultureInfo.InvariantCulture))
                  {
                      // CsvHelper использует отложенное чтение через 
                      // yeld, поэтому сразу преобразуем в список
                      catList = csv.GetRecords<Cat>().ToList();
                  }
              }
          }
      }
      
    • реализуем интерфейс IDataProvider (пишем метод getCats):

      public IEnumerable<Cat> getCats()
      {
          return catList;
      }
      
  4. Теперь в конструкторе окна меняем класс провайдера и всё продолжает работать

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        // Globals.dataProvider = new LocalDataProvider();
        Globals.dataProvider = new CSVDataProvider();
        CatList = Globals.dataProvider.getCats();
    }
    

ЗАДАНИЕ

  1. Подготовить набор данных (не менее 10 записей) с разными типами (обязательно должны быть: Int, Double, String, DateTime, Boolean)

  2. Реализовать класс CSVDataProvider для своей предметной области

  3. Поле с датой добавить в таблицу и указать формат вывода: Binding="{Binding YourColumn,StringFormat='dd.MM.yyyy'}"