Чтение онлайн

на главную - закладки

Жанры

Программирование для карманных компьютеров

Волков Владимир

Шрифт:

16. После проделанных манипуляций вторая созданная форма должна выглядеть так, как показано на рис. 6.14.

Рис. 6.14. Форма редактирования и добавления записи.

Работа с XML

Одной из полезных особенностей. NET CF является возможность легкой записи информации в XML-формате и последующее считывание ее из XML-файла. Из трех классов, предназначенных для работы с XML, в приложении будут использоваться классы XMLTextReader и XMLDocument. На самом деле можно было бы обойтись только классом XMLDocument, но класс XMLTextReader весьма полезен, и не хотелось бы пропускать демонстрацию его применения.

Фомат XML является форматом разметки (структурирования записи) данных. Как и HTML, XML основан на концепции тегов разметки. Но в отличие от HTML, теги XML не имеют предопределенных значений. Это значит, что, в общем случае, получатель документа может знать, как теги вложены друг в друга, какое положение один тег занимает относительно другого в документе, но ничего не может сказать относительно назначения этих тегов и информации, записанной в них. Придание значения той или иной информации, структурированной в XML-файле, ложится на плечи программы, разбирающей этот файл.

Код простейшего XML-файла показан в листинге 6.4.

Листинг 6.4

<?xml version="1.0" encoding="windows-1251"?>

<Y2005>

<Date>

<Index value = "0"/>

</Date>

<Date>

<Index value = "1"/>

</Date>

<Date>

<Index>2

</Index>

</Date>

</Y2005>

Первая

строка является описанием XML-документа. Она позволяет указывать версию XML и кодировку, в которой записан документ. Затем следует тег с именем Y2005. Этот тег состоит из открывающей (<Y2005>) и закрывающей (</Y2005>) частей. Внутри тега Y2005 расположены теги с именем Date. Все три тега Date не пустые, поэтому тоже имеют открывающую и закрывающую часть. Внутри тегов Date вложены теги Index. Первые два тега Index пустые, они состоят из одной части, которая одновременно открывает и закрывает этот тег. Внутри тега Index в первых двух случаях записано значение value. Значения, записанные внутри скобок тега, называются атрибутами. Любой тег может иметь любое количество атрибутов, но только одно значение. Значение записывается между открывающей и закрывающей частью тега.

Любой XML-документ должен начинаться с одного тега, который называется корневым тегом. В нашем случае корневым тегом является тег Y2005.

Что нам надо хранить в нашем XML-документе? Это должна быть информация о дате, для которой мы выполняем хронометраж, о категории работы, о времени начала работы, о времени ее окончания и примечания к каждой записи, если они необходимы. Структура нашего XML-файла приведена в листинге 6.5.

Листинг 6.5

Заголовочная часть:

<?xml version="1.0" encoding="windows-1251"?>

Корневой тег:

<Y2005>

Столько тегов Date, сколько дней мы будем контролировать:

<Date value = «20.08.2005» Cnt = "1">

Столько тегов Index, сколько отрезков времени мы учтем за день:

<Index Category="Work1" StartOf= «00.00» EndOf = «00.20» Note=""/>

<Index Category="Misc" StartOf= «00.20» EndOf = «00.40» Note=""/>

</Date>

</Y2005>

В каждом теге Date есть два атрибута. Атрибут value несет в себе дату, а Cnt – количество записей за день. В каждом теге Index есть четыре атрибута. В атрибуте Category указывается категория занятия, в атрибуте StartOf – время начала, в атрибуте EndOf – время окончания, а атрибут Note предназначен для хранения примечания.

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

Упражнение 6.2 (продолжение)

17. При запуске нашего приложения необходимо проверить, существует ли файл 2005.xml, в котором записаны результаты контроля времени, и файл Category.xml, в котором содержится список категорий. Если данные файлы не существуют, то их надо создать. Если файлы все еще существуют, то их нужно загрузить. Эти операции будут проводиться в обработчике события загрузки основной формы приложения. Но перед этим в класс формы нужно добавить две переменные. В окне Solution Explorer нужно выделить файл Form1.vb и из контекстного меню выполнить для этого файла команду View Code. Затем в самое начало кода нужно добавить строки, приведенные в листинге 6.6.

Листинг 6.6

Public Class Form1

Inherits System.Windows.Forms.Form

Friend WithEvents ListView1 As System.Windows.Forms.ListView

Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu

\'Добавленные переменные

Dim D As DateTime

Dim dirStr As String

18. Теперь можно создать процедуру обработчика события загрузки формы, код которой приведен в листинге 6.7. Листинг 6.7

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles MyBase.Load

\'Если файл с данными отсутствует в текущем каталоге, мы его создаем, для

\'этого сначала получаем полный путь каталога, в котором расположена

\'программа, в строковую переменную dirStr

dirStr = IO.Path.GetDirectoryName_

(Reflection.Assembly.GetExecutingAssembly.GetName.CodeBase.ToString)

\'Проверяем, есть ли файл c заданным именем по полученному пути

If Not System.IO.File.Exists(dirStr + «\2005.xml») Then

\'Если файла нет – создаем его

\'Создаем экземпляр XmlDocument

Dim myxmlDoc As New Xml.XmlDocument

\'Создаем корневой тег и добавляем его к документу

Dim oROOT As Xml.XmlElement = myxmlDoc.CreateElement(«Y2005»)

myxmlDoc.AppendChild(oROOT)

\'Получаем текущую дату в переменную myDate

Dim myDate As Date = Date.Now

myDate = DateAdd(DateInterval.Day, – 1, myDate)

\'Заполняем файл тегами Data от сегодняшнего дня до конца текущего года

While Not myDate.ToShortDateString = «31.12.2005»

myDate = DateAdd(DateInterval.Day, 1, myDate)

Dim oData As Xml.XmlElement = myxmlDoc.CreateElement(«Data»)

oROOT.AppendChild(oData)

Dim oValue As Xml.XmlAttribute = _ myxmlDoc.CreateAttribute(«value»)

Dim oIndex As Xml.XmlAttribute = _ myxmlDoc.CreateAttribute(«Cnt»)

oValue.InnerText = myDate.ToShortDateString

oIndex.InnerText = «-1»

oData.SetAttributeNode(oValue)

oData.SetAttributeNode(oIndex)

End While

\'Создаем заголовочную часть XML файла

Dim myPI As Xml.XmlProcessingInstruction = _

myxmlDoc.CreateProcessingInstruction_

(«xml», "version= 1.0 encoding=\'windows-1251 ")

myxmlDoc.InsertBefore(myPI, myxmlDoc.ChildNodes(0))

\'Сохраняем созданный документ

myxmlDoc.Save(dirStr + «\2005.xml»)

End If

\'Если файл со списком категорий отсутствует в текущем каталоге, мы его

\'создаем с пятью категориями Work1, Work2, Work3, Misc, Trash

If Not System.IO.File.Exists(dirStr + «\Category.xml») Then

If Not System.IO.File.Exists(dirStr + «\Category.xml») Then

Dim myxmlDoc As New Xml.XmlDocument

Dim oROOT As Xml.XmlElement = myxmlDoc.CreateElement(«Categoty»)

myxmlDoc.AppendChild(oROOT)

Dim oWork1 As Xml.XmlElement = myxmlDoc.CreateElement(«Work1»)

oROOT.AppendChild(oWork1)

Dim oWork2 As Xml.XmlElement = myxmlDoc.CreateElement(«Work2»)

oROOT.AppendChild(oWork2)

Dim oWork3 As Xml.XmlElement = myxmlDoc.CreateElement(«Work3»)

oROOT.AppendChild(oWork3)

Dim oMisc As Xml.XmlElement = myxmlDoc.CreateElement(«Misc»)

oROOT.AppendChild(oMisc)

Dim oTrash As Xml.XmlElement = myxmlDoc.CreateElement(«Trash»)

oROOT.AppendChild(oTrash)

Dim myPI As Xml.XmlProcessingInstruction = _

myxmlDoc.CreateProcessingInstruction_

(«xml», "version= 1.0 encoding=\'windows-1251 ")

myxmlDoc.InsertBefore(myPI, myxmlDoc.ChildNodes(0))

myxmlDoc.Save(dirStr + «\Category.xml»)

End If

D = DateTime.Now

Label1.Text = System.DateTime.Today.ToShortDateString

\'Вызываем процедуру загрузки данных в ListView

Data_Load(System.DateTime.Today.ToShortDateString)

End Sub

Чтобы создать и сохранить новый XML-документ, мы воспользовались классом XMLDocument, который позволяет представить существующий XML-документ в виде объекта с набором полей и методов для манипуляции этими полями. Он позволяет создавать и удалять элементы XML как по имени, так и по индексу, осуществлять поиск нужного элемента, заменять или дублировать элементы, сохранять измененный документ. Единственным недостатком этого класса является то, что документ полностью загружается в создаваемый объект. Поскольку на Pocket PC и файловая система, и оперативная память программы физически являются одним и тем же устройством, то просто происходит дублирование информации на время работы с документом.

19. Процедура загрузки данных для текущего дня в компонент ListView приведена в листинге 6.8.

Листинг 6.8

Private Sub Data_Load(ByVal MyDate As String)

\'Открываем файл, для это сначала получаем полный путь каталога,

\'в котором расположена программа в строковую переменную dirStr

dirStr = IO.Path.GetDirectoryName_

(Reflection.Assembly.GetExecutingAssembly.GetName.CodeBase.ToString)

\'Создаем экземпляр объекта XmlTextReader

Dim xmlrdrMy As New Xml.XmlTextReader(dirStr + «\2005.xml»)

Dim MyCount, MyIndex As Integer

Dim lvItem As ListViewItem

\'Не реагируем на пробелы и управляющие символы

xmlrdrMy.WhitespaceHandling = xmlrdrMy.WhitespaceHandling.None

\'Переходим к содержимому, пропуская заголовочную часть

xmlrdrMy.MoveToContent

\'В цикле считываем значения из файла, добавляем новую строку в ListView

\'для каждого тега Index и копируем значения атрибутов тега Index в

\'соответствующие

поля записи ListView

ListView1.Items.Clear

ListView1.Refresh

While Not xmlrdrMy.EOF

If xmlrdrMy.Name = «Data» Then

If xmlrdrMy.GetAttribute(«value») = MyDate Then

MyIndex = CInt(xmlrdrMy.GetAttribute(«Cnt»))

For MyCount = 0 To MyIndex – 1

xmlrdrMy.Read

lvItem = New ListViewItem(xmlrdrMy.GetAttribute(«Category»))

ListView1.Items.Add(lvItem)

ListView1.Items.Item(MyCount). SubItems.Add_

(xmlrdrMy.GetAttribute(«StartOf»))

ListView1.Items.Item(MyCount). SubItems.Add(xmlrdrMy.GetAttribute(«EndOf»))

ListView1.Items.Item(MyCount). SubItems.Add(xmlrdrMy.GetAttribute(«Note»))

Next

End If

End If

\'Считываем следующий элемент из файла XML

xmlrdrMy.Read

End While

\'Закрываем файл

xmlrdrMy.Close

End Sub

В этом случае мы воспользовались классом XmlTextReader для считывания информации из файла. Класс XmlTextReader также позволяет разбирать содержимое XML-документа, но он не создает копию файла в памяти, а считывает его в один проход элемент за элементом. Переход к следующему элементу осуществляется вызовом метода Read.

20. Теперь нужно создать процедуру сохранения данных текущего дня в файл. Эта процедура должна запускаться при переходе от одной даты к другой, а также в момент закрытия приложения. Ее код приведен в листинге 6.9.

Листинг 6.9

Private Sub Data_Save(ByVal MyDate As String)

Dim MyCount, MyIndex As Integer

\'Создаем объект XmlDocument

Dim myxml As New Xml.XmlDocument

dirStr = IO.Path.GetDirectoryName_

(Reflection.Assembly.GetExecutingAssembly.GetName.CodeBase.ToString)

\'Загружаем файл в объект XmlDocument

myxml.Load(dirStr + «\2005.xml»)

\'Перебираем все узлы уровня Data и находим сохраняемую дату

For MyCount = 0 To myxml.ChildNodes(1). ChildNodes.Count – 1

If myxml.ChildNodes(1). ChildNodes(MyCount). Attributes(0). InnerText = MyDate Then

\'Удаляем все содержимое этого узла

myxml.ChildNodes(1). ChildNodes(MyCount). RemoveAll

\'И заполняем его текущим содержимым полей ListView. При этом мы создаем

\'заново атрибуты узла Data и узлы Index со всеми атрибутами для каждой

\'строки ListView

\'Создаем атрибут value для текущего узла Data

Dim myValue As Xml.XmlAttribute = myxml.CreateAttribute(«value»)

\'Присваиваем атрибуту value значение текущей даты

myValue.InnerText = MyDate

\'Добавляем атрибут value к текущему узлу Data

myxml.ChildNodes(1). ChildNodes(MyCount). Attributes.Append(myValue)

\'Проделываем предыдущие операции с атрибутом Cnt

Dim mIndex As Xml.XmlAttribute = myxml.CreateAttribute(«Cnt»)

mIndex.InnerText = ListView1.Items.Count

myxml.ChildNodes(1). ChildNodes(MyCount). Attributes.Append(mIndex)

\'Заполняем узел Data вложенными элементами Index

For MyIndex = 0 To ListView1.Items.Count – 1

Dim oIndex As Xml.XmlElement = myxml.CreateElement(«index»)

myxml.ChildNodes(1). ChildNodes(MyCount). AppendChild(oIndex)

Dim oCategory As Xml.XmlAttribute = myxml.CreateAttribute(«Category»)

oCategory.InnerText = ListView1.Items(MyIndex). SubItems(0). Text

myxml.ChildNodes(1). ChildNodes(MyCount). ChildNodes_

(MyIndex). Attributes.Append(oCategory)

Dim oStartOf As Xml.XmlAttribute = myxml.CreateAttribute(«StartOf»)

oStartOf.InnerText = ListView1.Items(MyIndex). SubItems(1). Text

myxml.ChildNodes(1). ChildNodes(MyCount). ChildNodes_

(MyIndex). Attributes.Append(oStartOf)

Dim oEndOf As Xml.XmlAttribute = myxml.CreateAttribute(«EndOf»)

oEndOf.InnerText = ListView1.Items(MyIndex). SubItems(2). Text

myxml.ChildNodes(1). ChildNodes(MyCount). ChildNodes_

(MyIndex). Attributes.Append(oEndOf)

Dim oNote As Xml.XmlAttribute = myxml.CreateAttribute(«Note»)

oNote.InnerText = ListView1.Items(MyIndex). SubItems(3). Text

myxml.ChildNodes(1). ChildNodes(MyCount). ChildNodes_

(MyIndex). Attributes.Append(oNote)

Next

\'Если найден и заполнен требуемый узел Data, прекращаем перебор узлов

Exit For

End If

Next

\'Сохраняем документ в файл

myxml.Save(dirStr + «\2005.xml»)

End Sub

21. Остальные процедуры будут не столь объемны. После того как файл был загружен и его содержимое было отображено в элементе ListView, надо написать обработчики событий для щелчков на компонентах PictureBox, которые играют роль кнопок. Поскольку при написании этих обработчиков понадобятся переменные, через которые данные будут передаваться из формы в форму, нужно создать модуль и объявить в нем эти переменные.

22. Выполнить команду Project ? Add Module. На экран будет выведено соответствующее диалоговое окно. В строке Name нужно вместо предлагаемого имени указать имя Data, после чего нужно нажать кнопку Open. В окне редактора кода будет открыт пустой модуль. В нем нужно указать код, приведенный в листинге 6.10.

Листинг 6.10

Module Data

Public categorySt, startOfSt, endOfSt, noteSt As String

End Module

23. Процедура сохранения информации текущего дня при закрытии приложения описана в листинге 6.11. Листинг 6.11

Private Sub Form1_Closing(ByVal sender As Object, ByVal e As

System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

Data_Save(Label1.Text)

End Sub

24. Обработчик щелчка на кнопке PictureBox1, который осуществляет переход к предыдущему дню, приведен в листинге 6.12. Листинг 6.12

Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles PictureBox1.Click

Data_Save(Label1.Text)

D = DateAdd(DateInterval.Day, – 1, D)

Label1.Text = D.ToShortDateString

Data_Load(D.ToShortDateString)

End Sub

25. Обработчик щелчка на кнопке PictureBox2, который осуществляет переход к следующему дню, приведен в листинге 6.13. Листинг 6.13

Private Sub PictureBox2_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles PictureBox2.Click

Data_Save(Label1.Text)

D = DateAdd(DateInterval.Day, 1, D)

Label1.Text = D.ToShortDateString

Data_Load(D.ToShortDateString)

End Sub

26. Обработчик щелчка на кнопке PictureBox3, который отвечает за добавление очередной записи в текущий день, показан в листинге 6.14. Листинг 6.14

Private Sub PictureBox3_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles PictureBox3.Click

Dim lvIt As ListViewItem

\'Создаем диалоговую форму редактирования

Dim MyForm As New Form2

\'Устанавливаем флаг, показывающий, что был щелчок на кнопке 3

MyForm.Send = 3

\'Если ListView не пустой, копируем значения полей текущей записи в

\'переменные так, что время конца в текущей записи станет временем начала

\'в создаваемой записи

If ListView1.Items.Count > 0 Then

categorySt = ListView1.Items.Item_

(ListView1.Items.Count – 1). SubItems(0). Text

startOfSt = ListView1.Items.Item_

(ListView1.Items.Count – 1). SubItems(2). Text

endOfSt = startOfSt

noteSt = ""

Else

categorySt = ""

startOfSt = ""

endOfSt = ""

noteSt = ""

End If

\'Выводим на экран форму редактирования записи

If MyForm.ShowDialog = DialogResult.OK Then

\'И если редактирование завершилось щелчком на кнопке OK, добавляем новую

\'запись в ListView

lvIt = New ListViewItem(categorySt)

ListView1.Items.Add(lvIt)

ListView1.Items.Item.(ListView1.Items.Count – 1). SubItems.Add(startOfSt)

ListView1.Items.Item.(ListView1.Items.Count – 1). SubItems.Add(endOfSt)

ListView1.Items.Item.(ListView1.Items.Count – 1). SubItems.Add(noteSt)

End If

End Sub

27. Обработчик щелчка на кнопке PictureBox4, который отвечает за редактирование текущей записи, показан в листинге 6.15. Листинг 6.15

Private Sub PictureBox4_Click(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles PictureBox4.Click

\'Если в ListView есть выделенная строка, тогда редактируем

If ListView1.SelectedIndices.Count > 0 Then

Dim MyForm As New Form2

\'Сообщаем форме редактирования, что был щелчок на кнопке 4

MyForm.Send = 4

\'Копируем значения полей записи в переменные

categorySt = ListView1.Items(ListView1.SelectedIndices_(0)). SubItems(0). Text

startOfSt = ListView1.Items(ListView1.SelectedIndices(0)). SubItems(1). Text

endOfSt = ListView1.Items(ListView1.SelectedIndices(0)). SubItems(2). Text

noteSt = ListView1.Items(ListView1.SelectedIndices(0)). SubItems(3). Text

\'Если редактирование завершилось щелчком на кнопке OK, копируем возвращенные

\'значения переменных в соответствующие поля ListView

If MyForm.ShowDialog = DialogResult.OK Then

ListView1.Items(ListView1.SelectedIndices(0)). SubItems(0). Text = categorySt

ListView1.Items(ListView1.SelectedIndices(0)). SubItems(1). Text = startOfSt

ListView1.Items(ListView1.SelectedIndices(0)). SubItems(2). Text = endOfSt

ListView1.Items(ListView1.SelectedIndices(0)). SubItems(3). Text = noteSt

End If

End If

End Sub

Поделиться:
Популярные книги

Черный дембель. Часть 2

Федин Андрей Анатольевич
2. Черный дембель
Фантастика:
попаданцы
альтернативная история
4.25
рейтинг книги
Черный дембель. Часть 2

Кодекс Крови. Книга ХIV

Борзых М.
14. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХIV

Магия чистых душ 3

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Магия чистых душ 3

Жестокая свадьба

Тоцка Тала
Любовные романы:
современные любовные романы
4.87
рейтинг книги
Жестокая свадьба

Усадьба леди Анны

Ром Полина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Усадьба леди Анны

Измена. Возвращение любви!

Леманн Анастасия
3. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Возвращение любви!

Два лика Ирэн

Ром Полина
Любовные романы:
любовно-фантастические романы
6.08
рейтинг книги
Два лика Ирэн

Опасная любовь командора

Муратова Ульяна
1. Проклятые луной
Фантастика:
фэнтези
5.00
рейтинг книги
Опасная любовь командора

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

Мымра!

Фад Диана
1. Мымрики
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Мымра!

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Имперский Курьер

Бо Вова
1. Запечатанный мир
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Имперский Курьер

Страж. Тетралогия

Пехов Алексей Юрьевич
Страж
Фантастика:
фэнтези
9.11
рейтинг книги
Страж. Тетралогия

Сердце дракона. Танец с врагом

Серганова Татьяна
2. Танец с врагом
Любовные романы:
любовно-фантастические романы
5.25
рейтинг книги
Сердце дракона. Танец с врагом