Реакции на события в DataTable — КиберПедия 

История создания датчика движения: Первый прибор для обнаружения движения был изобретен немецким физиком Генрихом Герцем...

Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...

Реакции на события в DataTable

2022-09-11 27
Реакции на события в DataTable 0.00 из 5.00 0 оценок
Заказать работу

Таблица экзаменов является дочерней (подчиненной) по отношению к таблице студентов и связана с ней по ключевым полям (ID и StudID). Такой тип связи часто называют PK-FK (Primary-Key-Forign Key). При вводе новой записи в родительскую таблицу подчиненная таблица ведет себя инертно — в ней не появляются новые строки со списком экзаменов нового студента. Вам придется вручную ввести несколько строк в таблицу экзаменов. Эта рутинная работа будет сильно утомлять не только вас, но и пользователей вашего приложения. В некоторых сценариях работы с данными хочется это исправить и автоматизировать процесс появления строк в подчиненной таблице.

Очевидно, что добавление экзаменов надо делать в ответ на событие, которое соответствует появлению нового студента. В документации по классам библиотеки.NET Framework находим, что класс DataTable способен обработать два события (RowChanging и RowChanged), которые прямо связаны с нашим намерением. Первое происходит в момент изменения строки таблицы, а второе — после того, как изменения в строке успешно завершились. Выбираем второе и вводим реакцию на него в класс формы. Это делается стандартным способом — добавлением делегата в список делегатов события RowChanged. Введите следующий код в начало метода RelateAndBind.

//=== Добавляем адрес функции обработки события в коллекцию делегатов, поддерживаемую событием RowChanged

ds.Tables[0].RowChanged +=

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

Просмотрите код заготовки. Я изменил автоматически сгенерированное имя функции на OnStudsRowChanged. Теперь оно больше соответствует своему назначению. Второй параметр функции (задания делегата) передает ссылку на объект вспомогательного класса DataRowChangeEventArgs, который содержит важную информацию о конкретном типе изменения. Для того, чтобы узнать какие изменения в принципе отслеживаются, смотрите справку по перечислению DataRowAction. Мы используем эту информацию для фильтрации только одного типа изменений (Add).

void OnStudsRowChanged(object sender, DataRowChangeEventArgs e)

{

DataTable exams = ds.Tables[1]; // Ссылка на подчиненную таблицу экзаменов

if (e.Action == DataRowAction.Add) // Если в первой таблице появилась новая строка

{

int num = 0;

foreach (string c in courses) // Массив с именами предметов должен существовать

{

    if (num++!= rand.Next(courses.Length))

      ds.Tables[1].Rows.Add(CreateRandomExam((int)e.Row["ID"], c));

}

}

}

В нашей версии предполагается, что названия курсов лекций фиксированы и хранятся в массиве текстовых строк courses. Если пользователь вставил в таблицу студентов новую запись (строку), то во второй таблице появляются несколько строк. Для связывания их с родительской строкой первой таблицы (связь типа PK-FK) необходимо правильно установить значение столбца StudID, которое соответствует ключевому полю ID первой таблицы (см. код присвоения e.Row["ID"]).

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

Это действительно так, если строки добавляются в новую, пустую таблицу. Однако, обработчик события дает сбой при попытке вставить новые строки в старую таблицу, то есть ту, которая восстанавливается из файла. В чем же дело? Попробуйте самостоятельно вычислить причину такого поведения и способ его коррекции.

Вы, вероятно, догадались, что при добавлении строк, которое происходит при чтении данных из файла, возбуждается событие RowChanged и мы автоматически добавляем лишнее множество экзаменов к тем, которые уже есть в файле. Вот один из способов решения этой проблемы. Перед восстановлением всего набора данных из файла, надо выключить реакцию на событие RowChanged и вновь включить ее после прочтения данных из файла. Для этого надо пользоваться операциями –= и += события RowChanged нужной таблицы.

Канонизация имен студентов

В данный момент мы можем ввести двух студентов с именами: "Joe Doe" и " Joe    Doe " (второе содержит массу лишних пробелов) и они будут считаться разными, хотя семантически они одинаковы. Для того, чтобы придать полю Name стандартный формат, давно напрашивается вставка метода Trim(string), который убирает пробелы не только в начале и конце имени, но и лишние пробелы между отдельными словами. Рассмотрим, как можно сделать это с помощью класса StringBuilder.

string Trim (string sOld)

{

StringBuilder sNew = new StringBuilder();

bool wasSpace = true;

for (int i=0; i<sOld.Length; i++)

{

bool isSpace = sOld[i] == ' ';

if (!(wasSpace && isSpace))

sNew.Append (sOld[i]);

wasSpace = isSpace;

}

return sNew.ToString().TrimEnd();

}

В методе Trim используется объект класса StringBuilder. Он позволяет работать со строкой текста, как с коллекцией символов. Сначала коллекция пуста, затем в цикле прохода по старой строке мы добавляем в нее только те символы, которые считаем нужными. Здесь работает метод Append, который меет 18 перегруженных версий и, поэтому, позволяет очень гибко работать с вновь генерируемой строкой. Обязательно просмотрите справку по этому методу.

Задействуйте процесс унификации имен, добавив в начало обработчика события RowChanged следующий код:

ds.Tables[0].RowChanged -= OnStudsRowChanged;

e.Row["Name"] = Trim(e.Row["Name"].ToString());

ds.Tables[0].RowChanged += OnStudsRowChanged;

На лекции мы осуждали необходимость выключения (см. операции –= и +=) и повторного включения задания делегата, реагирующего на изменения в строке таблицы студентов. Что будет, если пренебречь этим?

Временное выключение делегата необходимо, чтобы не получить бесконечный цикл обработки события RowChanged, так как присвоение e.Row["Name"] вновь генерирует событие RowChanged. Теперь коррекция имени будет производиться не только при добавлении новой строки, но и при изменении существующей. Проверьте это и объясните.

Вспомнив о возможностях класса Regex, разработаем новую версию метода Trim, которая состоит из одной строки кода. Замените существующую версию на новую.

string Trim(string s) { return new Regex(@"\s{2,}").Replace(s.Trim(), " "); }

При создании объекта класса Regex мы задаем шаблон регулярного выражения ("\s{2,}"). Мета-символ \s означает space (пустые символы). Шаблон говорит классу Regex, что он должен искать подстроки, которые содержат 2 или более пустых символов. Метод Replace класса Regex осуществляет замену всех найденных в строке s вхождений подстроки, определенной шаблоном, на строку " ", которая содержит только один пробел. Строка s предварительно обрабатывается методом Trim() класса string, что необходимо для уничтожения крайних пробелов.

Еще лучшим решением рассматриваемой проблемы будет добавление в проект класса Helper с методом GetName, который выуживает имя из строки символов с помощью механизма регулярных выражений. Мы использовали такой метод в предыдущей части курса.


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.014 с.