Для сохранения и загрузки наборов данных



Мы поможем в написании ваших работ!


Мы поможем в написании ваших работ!



Мы поможем в написании ваших работ!


ЗНАЕТЕ ЛИ ВЫ?

Для сохранения и загрузки наборов данных



Файлы, содержащие наборы данных, имеют специальный текстовый формат, называемый XML-форматом; чтобы это подчеркнуть, для них выбрано нестандартное расширение studXml.

Формат XML в настоящее время является наиболее распространенным текстовым форматом для хранения наборов данных, поэтому для работы с этим форматом в .NETFrameWork предусмотрен ряд классов. Одним из простейших в использовании является класс XmlSerializer (XML-сериализатор), позволяющий сохранять и считывать из файла данные, связанные с отдельным объектом или коллекцией объектов. При создании объекта типа XmlSerializer необходимо указать тип того объекта, данные которого требуется записать в файл или прочесть из файла (данными служат все открытые поля, а также открытые свойства объекта, доступные одновременно для чтения и записи). Метод Serialize записывает данные из объекта в файл, а метод Deserialize создает объект указанного типа и заполняет его данными, прочитанными из файла. В программе использован вариант этих методов, у которых в качестве первого параметра указывается файловый поток (типа StreamReader или StreamWriter). Сериализуемым объектом является список List<student> (т.е. список объектов student), который связывается с компонентом bindingSource1 и хранится в его свойстве DataSource.

Свойство таблицы IsCurrentCellDirty равно true, когда значение текущей ячейки уже изменено, однако еще не зафиксировано. Фиксация изменений (committing) происходит при выходе из режима редактирования при условии, что эти изменения успешно прошли проверку на правильность.

 

Добавьте в форму Form1 невизуальные компоненты типа OpenFileDialog и SaveFileDialog, а также компонент меню MenuStrip ( эти компоненты получат имена openFileDialog1, saveFileDialog1, menuStrip).

Используя конструктор меню, создайте в компоненте menuStrip1 пункт меню первого уровня &File и с помощью окна Свойств измените имя этого пункта (т.е. свойство Name) на file1. В выпадающем меню связанном с пунктом File, создайте три пункта меню с текстом &New, &Open…, &SaveAs… .

 

 

Настройте свойства добавленных компонентов и пунктов меню следующим образом

openFileDialog1, saveFileDialog1: DefaultExc = studXml,

Filter = Student data files|*.studXml

пункт меню New (группаFile): Name = new1

пункт меню Open (группаFile): Name = open1

пункт меню SaveAs (группаFile): Name = saveAs1

 

В начало файла Form1.cs добавьте следующие операторы:

using System.IO;

using System.Xml.Serialization;

 

В описание класса Form1 добавьте новое поле:

private XmlSerializer xmls = new XmlSerializer (typeof(List<student>));

 

Дополните конструктор класса Form1

 

public Form1()

{

InitializeComponent();

bindingSource1.DataSource = new List<student>();

}

 

Опишите в классе Form1 новый метод SaveData

private void SaveData ( string name )

{

if ( name == "" || dataGridView1.RowCount == 1)

return;

StreamWriter sw = new StreamWriter (name, false, Encoding.Default);

xmls.Serialize(sw, bindingSource1.DataSource);

sw.Close()

}

 

Определите обработчики события DropDownOpening для пункта меню file, события Click для пунктов меню new1, open1, saveAs1, а также события FormClosing для формы Form1

 

private void file1_DropDownOpening ( object sender, EventArgs e)

{

saveAs1.Enabled = dataGridView1.RowCount > 1;

}

 

private void new1_Click (object sender, EventArgs e)

{

SaveData(saveFileDialog1.FileName);

bindingSource1.DataSource =new List<student>();

dataGridView1.CurrentCell = dataGridView1[0, 0];

saveFileDialog1.FileName ="";

Text ="Students";

}

 

 

private void open1_Click ( object sender, EventArgs e)

{

openFileDialog1.FileName ="";

if (openFileDialog1.ShowDialog() == DialogResult.OK)

{

SaveData(saveFileDialog1.FileName);

string s = openFileDialog1.FileName;

StreamReader sr = new StreamReader(s, Encoding.Default);

bindingSource1.DataSource=xmls.Deserialize(sr);

sr.Close();

saveFileDialog1.FileName=s;

Text= "Students - " + Path.GetFileNameWithoutExtension(s);

}

 

}

 

private void saveAs1_Click( object sender, EventArgs e)

{

if (saveFileDialog1.ShowDialog() == DialogResult.OK)

{

string s = saveFileDialog1.FileName;

SaveData(s);

Text ="students - " + Path.GetFileNameWithoutExtension(s);

}

}

 

private void Form1_FormClosing(object sender, FormClosingEventArgs e)

{

SaveData(saveFileDialog1.FileName);

}

 

Добавленные команды меню позволяют сохранить текущий непустой набор данных в файл с указанным именем, прочесть из файла ранее сохраненный набор данных и создать пустой набор данных. Имя файла, связанного с текущим набором данных, отображается в заголовке окна после имени формы.

Имя файла, связанного с текущим набором данных, хранится в свойстве FileName компонента saveFileDialog; если это свойство является пустой строкой, значит, текущий набор данных еще не связан с файлом.

 

Если текущей строкой является последняя строка таблицы (строка NewRow), то попытка прочесть набор данных из файла приводит к ошибке времени выполнения. Эта ошибка объясняется тем, что перед загрузкой нового набора данных между таблицей и компонентом bindingSource1 происходит попытка обмена данных, взятых из текущей строки, которая завершается неудачей, поскольку строка NewRow не связана с реальным элементом набора данных.

Для исправления нужно добавить в метод open1_Click два новых оператора (выделены жирным шрифтом в следующем листинге)

 

privatevoid open1_Click ( object sender, EventArgs e)

{

openFileDialog1.FileName ="";

if (openFileDialog1.ShowDialog() == DialogResult.OK)

{

SaveData(saveFileDialog1.FileName);

string s = openFileDialog1.FileName;

StreamReader sr = new StreamReader(s, Encoding.Default);

bindingSource1.SuspendBinding();

bindingSource1.DataSource=xmls.Deserialize(sr);

bindingSource1.ResumeBinding();

sr.Close();

saveFileDialog1.FileName=s;

Text= "Students - " + Path.GetFileNameWithoutExtension(s);

}

}

 

В результате перед загрузкой нового набора данных компонент bindingSource1 временно отсоединяется от компонента dataGridView1, поэтому никакие действия, связанные с обработкой текущей ячейки, в ходе загрузки не выполняются. После загрузки соединение восстанавливается.

 

Если при записи набора данных текущей ячейкой является одна из ячеек последней строки (строки NewRow), то в файл, кроме «настоящих» элементов набора данных, записывается дополнительный элемент с данными, взятыми из последней строки таблицы (этот элемент, в частности, будет содержать пустое поле Фамилия). Как и в случае предыдущей ошибки, причина заключается в особой обработке текущей строки, которая в данной ситуации не связана с реальным элементом набора данных.

Для исправления нужно изменить метод SaveData

 

private void SaveData ( string name )

{

if ( name == "" || dataGridView1.RowCount == 1)

return;

if (dataGridView1.CurrentRow.IsNewRow)

dataGridView1.CurrentCell =

dataGridView1[0, dataGridView1.RowCount - 2];

 

StreamWriter sw = new StreamWriter (name, false, Encoding.Default);

xmls.Serialize(sw, bindingSource1.DataSource);

sw.Close();

}

 

В результате перед сохранением набора данных выполняется проверка, является ли текущая строка строкой NewRow, и если является, то текущей ячейкой делается первая ячейка предыдущей строки (заметим, что предыдущая строка всегда существует, так как ранее в методе SaveDataпроверяется, что таблица содержит хотя бы две строки).

 

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

Для исправления данного недочета определите обработчик события CurrentCellDirtyStateChange для компонента dataGridView1следующим образом:

 

private void dataGridView1_CurrentCellDirtyStateChanged(object sender,

EventArgs e)

{

menuStrip1.Enabled = !dataGridView1.IsCurrentCellDirty;

}

 

 



Последнее изменение этой страницы: 2016-04-23; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 34.226.244.254 (0.007 с.)