Прежде всего, я обеспечил приложение возможностью соединения с базой данных Articles. С этой целью мною был добавлен программный компонент SqlConnection. Идентификатор этого компонента будет храниться в поле sqlConnection1 класса Form1.
Чтобы приложение могло корректным образом соединиться с базой данных Articles свойство ConnectionString объекта SqlConnection1 должно быть отредактировано следующим образом:
DataSource=.\SQLEXPRESS;AttachDbFilename=D:\Work\ArticlesApp\ArticlesApp\Articles.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True
Для того чтобы приложение могло загружать содержимое таблицы Tree базы данных Articles, хранящей структуру дерева статей, я добавил в него адаптер SqlDataAdapter, использующий соединение SqlConnection1. Таким образом ссылка на адаптер данных будет хранится в поле SqlDataAdapter1.
После добавления адаптера необходимо создать набор данных DataSet. Выбрав на панели инструментов одноимённый компонент, я создал набор данных DataSet1, содержащий обе таблицы базы данных Articles.
Создание узла дерева
Создание дерева начинается с того, что пользователь запускает приложение, щелкает правой клавишей мыши пустое окно дерева и выбирает из контекстного меню строку Добавить статью. В результате на экране появляется диалоговое окно, показанное на рисунке ниже, где пользователь может ввести информацию для узла дерева:
|
|
Реализация процесса добавления статьи состоит в написании обработчика события для кнопки Добавить статью контекстного меню contextMenuStrip1. Ниже приведён обработчик для этого события:
private void добавитьToolStripMenuItem_Click(object sender, EventArgs e)
{
if (treeView1.SelectedNode!= null)
{
int id = (int)treeView1.SelectedNode.Tag;
AddNode(id);
UpdateTree();
}
else
{
// Пустой список
if (treeView1.Nodes.Count == 0)
{
AddNode(0);
UpdateTree();
}
}
}
При самом первом запуске приложения и пустой базе данных в дереве treeView1 не выделено ни одного элемента, т.к. их там попросту нет. Соответственно, количество узлов дерева treeView1.Nodes.Count равно нулю. В этом случае моё приложение вызывает два метода:
AddNode(0);
UpdateTree();
Метод AddNode
Метод AddNode, определенный в моём приложении, создает узел дерева. В качестве единственного параметра этому методу нужно передать идентификатор родительского узла. Так как в первый раз пользователь создает корневой узел, то передаем методу AddNode нулевое значение.
Что же касается метода UpdateTree, то он тоже определен в моём приложении. Его задачей является наполнение окна дерева treeView1 содержимым таблицы Tree базы данных Articles. Я вызываю этот метод всякий раз после внесения изменений в структуру дерева (т.е. после добавления или удаления узлов дерева).
Для того чтобы содержимое дерева отображалось сразу после запуска приложения, я добавил вызов метода UpdateTree в конструктор класса Form1:
|
|
public Form1()
{
InitializeComponent();
UpdateTree();
}
В том случае, если в дереве есть узлы, и пользователь выделил какой-либо узел левой клавишей мыши или при помощи клавиатуры, наш обработчик событий добавитьToolStripMenuItem_Click выполняет следующие действия:
if (treeView1.SelectedNode!= null)
{
int id = (int)treeView1.SelectedNode.Tag;
AddNode(id);
UpdateTree();
}
Вначале он извлекает из свойства treeView1.SelectedNode.Tag идентификатор строки таблицы Tree, соответствующий выделенному узлу. Этот идентификатор записывается в данное свойство методом UpdateTree в процессе построения дерева.
Замечу, что данный идентификатор обозначает узел, являющийся родительским по отношению к создаваемому узлу. Обработчик событий добавитьToolStripMenuItem_Click передает этот идентификатор методу AddNode, а затем перерисовывает обновленное дерево методом UpdateTree:
AddNode(id);
UpdateTree();
Рассмотрим реализацию метода AddNode, служащего для добавления нового узла в дереве заголовков статей и добавления всех необходимых записей в базу данных Articles:
public void AddNode(int id)
{
Form2 dialog = new Form2();
if (DialogResult.Yes == dialog.ShowDialog())
{
sqlConnection1.Open();
try
{
SqlCommand cmd = new SqlCommand("sp_InsertNode",sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter param = cmd.Parameters.Add("RETURN_VALUE",SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("@parent_id", SqlDbType.Int).Value = id;
cmd.Parameters.Add("@title", SqlDbType.VarChar).Value =dialog.Title;
cmd.Parameters.Add("@weight", SqlDbType.Int).Value =dialog.Weight;
cmd.ExecuteNonQuery();
int tree_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
cmd = new SqlCommand("sp_InsertDocument", sqlConnection1);
cmd.CommandType = CommandType.StoredProcedure;
param = cmd.Parameters.Add("RETURN_VALUE", SqlDbType.Int);
param.Direction = ParameterDirection.ReturnValue;
cmd.Parameters.Add("@tree_id", SqlDbType.Int).Value = tree_id;
cmd.Parameters.Add("@document", SqlDbType.Text).Value =dialog.Document;
cmd.ExecuteNonQuery();
int document_id = (int)cmd.Parameters["RETURN_VALUE"].Value;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка");
}
sqlConnection1.Close();
}
}
В самом начале работы метод AddNode отображает диалоговое окно для добавления новой статьи. Это диалоговое окно представляет собой класс Form2, добавленный непосредственно в проект приложения ArticlesApp.
Если пользователь завершил работу с данным диалоговым окном нажатием кнопки Сохранить, то метод AddNode извлекает данные, введённые пользователем и добавляет их в таблицы базы данных Articles:
Form2 dialog = new Form2();
if (DialogResult.Yes == dialog.ShowDialog())
{
...
Для добавления данных, прежде всего, открывается соединение с базой данных: sqlConnection1.Open();
Все дальнейшие операции выполняются в теле оператора try-catch, что позволяет перехватывать ошибки и отображать текст сообщений об ошибках на экране:
try
{
...
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка");}
После обновления содержимого базы данных метод AddNode закрывает соединение с базой данных SqlConnection1.Close();.