- •Введение
- •1 Компоненты Visual C#
- •1.1 Компонент класса GroupBox
- •1.2 Компонент класса RadioButton
- •1.3 Компонент класса CheckBox
- •1.4 Компонент класса ListBox
- •1.5 Компонент класса Form
- •1.6 Компонент класса PictureBox
- •1.7 Компонент класса Timer
- •1.8 Компонент класса MenuStrip
- •1.9 Компоненты классов ToolStrip и ToolStripButton
- •1.10 Компоненты классов StatusStrip и ToolStripStatusLabel
- •1.11 Компоненты классов OpenFileDialog и SaveFileDialog
- •1.12 Компонент класса TreeView
- •2 Примеры выполнения практических заданий
- •2.1 Стандартные алгоритмы
- •2.2 Элементы выбора
- •2.3 Простейшие классы
- •2.4 Графика
- •2.5 Диалоговые окна
- •2.6 Комплексное задание
- •2.7 Наследование
- •2.8 Древовидные структуры
- •Список литературы
2.8 Древовидные структуры
Задание: Структура «дерева» имеет вид, описанный в таблице 12.
Таблица 12 – Структура «дерева»
Уро- |
Описание элементов |
Строка отображаемой |
вень |
«дерева» |
информации |
1 |
список разделов |
'Это корень дерева' |
2 |
шифр раздела |
'Наименование раздела: '+ |
|
|
+<наименование раздела> |
3 |
наименование раздела |
'Шифр раздела: '+<шифр раздела> |
|
список книг |
|
4 |
наименование книги |
'Наименование раздела: '+ |
|
|
+<наименование раздела> |
5 |
автор |
'Наименование книги: '+ |
|
количество страниц |
+<наименование книги> |
Примечание – Вместо строки в угловых скобках (< >) выводить реальные данные; знак «+» не выводится
Разработать программу, обеспечивающую формирование заданной структуры «дерева» (добавление, изменение, удаление элементов) с использованием диалоговых окон. Предусмотреть в диалоговых окнах проверку правильности ввода данных. Разработать классы, обеспечивающие хранение данных. Для хранения списков данных использовать экземпляры класса List. Предусмотреть запрет недопустимых действий. Реализовать для выбранного элемента дерева отображение необходимой информации в компоненте класса
TextBox.
При анализе предметной области можно выделить два класса: раздел и книга.
Опишем реализацию классов TBook (книга) и TSection (раздел) в отдельном модуле, который добавим в программу через меню «Проект → Добавить новый элемент → Файл с текстом программы». Классы должны быть описаны в том же пространстве имен, что и основная программа. Также должно быть подключено необходимое пространство имен.
using System.Collections.Generic;
namespace ...
{
public class TBook
{
public string Name, Autor; public int Count;
}
45
public class TSection
{
public string Name, Shift; /* Список книг раздела */
public List<TBook> Books = new List<TBook>();
}
}
Для решения поставленной задачи на основной форме (Main_F) потребуются компоненты:
Catalog_L класса Label для подписи компонента Catalog_TV;
Catalog_TV класса TreeView для отображения «дерева»;
Add_B класса Button для активизации добавления элемента;
Change_B класса Button для активизации редактирования выбранного
элемента;
Del_B класса Button для активизации удаления выбранного элемента;
Info_L класса Label для подписи компонента Info_TB;
Info_TB класса TextBox для вывода информации для выбранного эле-
мента «дерева»; Установим следующие значения свойств компонентов (таблица 13):
Таблица 13 – Значения свойств компонентов основной формы для примера программы, использующей древовидную структуру
Компонент.Свойство |
Значение |
Catalog_L.Text |
Структура &каталога |
Add_B.Text |
Доб&авить |
Change_B.Text |
И&зменить |
Del_B.Text |
Уда&лить |
Info_TB.ReadOnly |
true |
|
|
Info_L.Text |
Информац&ия |
Создадим, с помощью строенного редактора, в компоненте Catalog_TV «корень дерева» в виде строки «Список разделов».
На форме диалогового окна работы с разделом (Section_F) потребуются компоненты:
Shifr_L класса Label для подписи компонента Shifr_TB;
Shifr_TB класса TextBox для ввода шифра раздела;
Name_L класса Label для подписи компонента Name_TB;
Name_TB класса TextBox для ввода наименования раздела;
Ok_B класса Button для подтверждения добавления или редактирова-
ния;
Cancel_B класса Button для отмены добавления или редактирования.
46
Установим следующие значения свойств компонентов (таблица 14):
Таблица 14 – Значения свойств компонентов диалогового окна для работы с разделом
Компонент.Свойство |
Значение |
Section_F.FormBorderStyle |
FixedDialog |
|
|
Section_F.AcceptButton |
Ok_B |
|
|
Section_F.CancelButton |
Cancel_B |
|
|
Section_F.MinimizeBox |
false |
|
|
Section_F.MaximizeBox |
false |
|
|
Section_F.ShowInTaskbar |
false |
|
|
Shifr_L.Text |
Ши&фр |
Name_L.Text |
Наи&менование |
Ok_B.Text |
Ok |
Ok_B.DialogResult |
OK |
|
|
Cancel_B.Text |
Отм&ена |
Cancel_B.DialogResult |
Cancel |
|
|
На форме диалогового окна работы с книгой (Book_F) потребуются компоненты:
Name_L класса Label для подписи компонента Name_TB;
Name_TB класса TextBox для ввода наименования книги;
Autor_L класса Label для подписи компонента Autor_TB;
Autor_TB класса TextBox для ввода автора книги;
Count_L класса Label для подписи компонента Count_NUD;
Count_NUD класса NumericUpDown для ввода количества страниц кни-
ги;
Ok_B класса Button для подтверждения добавления или редактирова-
ния;
Cancel_B класса Button для отмены добавления или редактирования. Установим следующие значения свойств компонентов (таблица 15).
Будем считать, что максимальное количество страниц у книги – 5000:
Таблица 15 – Значения свойств компонентов диалогового окна для работы с книгой
Компонент.Свойство Значение
Book_F.FormBorderStyle FixedDialog
Book_F.AcceptButton Ok_B
Book_F.CancelButton Cancel_B
Book_F.MinimizeBox false
47
Продолжение таблицы 15
Компонент.Свойство |
Значение |
Book_F.MaximizeBox |
false |
|
|
Book_F.ShowInTaskbar |
false |
|
|
Name_L.Text |
Наи&менование |
Autor_L.Text |
А&втор |
Count_NUD.Minimum |
1 |
|
|
Count_NUD.Maximum |
5000 |
|
|
Count_NUD.Value |
1 |
|
|
Count_L.Text |
Количество &страниц |
Ok_B.Text |
Ok |
Ok_B.DialogResult |
OK |
|
|
Cancel_B.Text |
Отм&ена |
Cancel_B.DialogResult |
Cancel |
|
|
Опишем событие Shown формы Section_F:
private void Section_F_Shown(object sender, EventArgs e)
{
Shifr_TB.Focus();
}
Опишем событие FormClosing формы Section_F:
private void Section_F_FormClosing(object sender, FormClosingEventArgs e)
{
/* Алгоритм проверки правильности ввода приводился в предыдущих заданиях */
}
Аналогично описываются события для формы Book_F.
В классе TMain_F опишем поле для хранения коллекции разделов:
List<TSection> Catalog = new List<TSection>();
Опишем событие Click кнопки Add_B:
private void Add_B_Click(object sender, EventArgs e)
{
/* Проверка, что что-либо выбрано */ if (Catalog_TV.SelectedNode != null)
{
/* Выбран список разделов, если элемент |
имеет уровень 1 */ |
if (Catalog_TV.SelectedNode.Level == 0) |
// Выбран список |
{ |
// разделов |
Section_F Dialog = new Section_F(); |
|
48
/* Установка заголовка формы и значений “по умолчанию” для всех полей ввода */
...;
if (Dialog.ShowDialog() == DialogResult.OK)
{
TSection Section = new TSection(); Section.Shift = Dialog.Shifr_TB.Text.Trim(); Section.Name = Dialog.Name_TB.Text.Trim();
/* Созданный раздел необходимо добавить в список разделов */
Catalog.Add(Section);
/* Добавление элемента дерева для шифра и запоминание его во временную переменную для последующей работы с ним */
TreeNode TempNode = Catalog_TV.SelectedNode.Nodes.Add (Section.Shift);
/* Добавление элементов дерева для наименования раздела и списка книг */
TempNode.Nodes.Add("Наименование: "+Section.Name); TempNode.Nodes.Add("Список книг");
}
}
else
{Выбран список книг, если элемент имеет уровень 3 и является вторым в списке элементов родителя}
if (Catalog_TV.SelectedNode.Level == 2 && Catalog_TV.SelectedNode.Index == 1)
{
Book_F Dialog = new Book_F();
/* Установка заголовка формы и значений “по умолчанию” для всех полей ввода */
...;
if (Dialog.ShowDialog() == DialogResult.OK)
{
TBook Book = new TBook();
/* Заполнение свойств книги и */
...; /* Для получения раздела, в который добавляется
книга, необходимо получить номер раздела в списке, который равен индексу элемента дерева, содержащего шифр */
TSection Section = Catalog.ElementAt( Catalog_TV.SelectedNode.Parent.Index);
Section.Books.Add(Book);
/* Добавление элементов дерева */
...;
}
}
else
MessageBox.Show("Добавление возможно только в списки разделов или книг", "Информация");
}
else
49
MessageBox.Show("Выберите список для добавления", "Информация");
}
Опишем событие Click кнопки Change_B:
private void Change_B_Click(object sender, EventArgs e)
{
if (Catalog_TV.SelectedNode != null)
{
/* Редактирование возможно, если выбран раздел (уровень 2) или книга (уровень 4) */
if (Catalog_TV.SelectedNode.Level == 1 || Catalog_TV.SelectedNode.Level == 3)
{
if (Catalog_TV.SelectedNode.Level == 1) // Выбран раздел
{
/* Получение выбранного раздела */ TSection Section = Catalog.ElementAt(
Catalog_TV.SelectedNode.Index); Section_F Dialog = new Section_F();
...; // Подготовка диалогового окна к работе if (Dialog.ShowDialog() == DialogResult.OK)
{
...; // Изменение свойств раздела на новые
/* Изменение всех элементов дерева, связанных
с разделом */
Catalog_TV.SelectedNode.Text = Section.Shift; Catalog_TV.SelectedNode.Nodes[0].Text =
"Наименование: "+Section.Name;
}
}
else
{// Выбрана книга /* Для получения раздела, в который добавляется
книга, необходимо получить номер раздела в списке, который равен индексу элемента дерева, содержащего шифр */
TSection Section = Catalog.ElementAt( Catalog_TV.SelectedNode.Parent.Parent.Index);
/* Получение выбранной книги */ TBook Book = Section.Books.ElementAt(
Catalog_TV.SelectedNode.Index);
Book_F Dialog = new Book_F();
/* Выполнение действий, аналогичных изменению раздела */
...;
}
}
else
MessageBox.Show("Изменить можно только раздел или книгу", "Информация");
50
}
else
MessageBox.Show("Выберите раздел или книгу для изменения", "Информация");
}
Опишем событие Click кнопки Del_B:
private void Del_B_Click(object sender, EventArgs e)
{
if (Catalog_TV.SelectedNode != null)
{
/* Удаление возможно, если выбран раздел (уровень 2) или
книга (уровень 4) */
if (Catalog_TV.SelectedNode.Level==1 || Catalog_TV.SelectedNode.Level==3)
{
if (Catalog_TV.SelectedNode.Level == 1) // Раздел
/* Удаление выбранного раздела из списка разделов */ Catalog.RemoveAt(Catalog_TV.SelectedNode.Index);
else // Книга
{
/* Получение раздела, к которому относится книга */ TSection Section = Catalog.ElementAt(
Catalog_TV.SelectedNode.Parent.Parent.Index); /* Удаление выбранной книги из раздела */
Section.Books.RemoveAt(Catalog_TV.SelectedNode.Index);
}
/* Удаление элемента “дерева” со всеми потомками */ Catalog_TV.SelectedNode.Remove();
}
else
MessageBox.Show("Удалить можно только раздел или книгу", "Информация");
}
else
MessageBox.Show("Выберите раздел или книгу для удаления", "Информация");
}
Опишем событие AfterSelect компонента Catalog_TV:
private void Catalog_TV_AfterSelect(object sender, TreeViewEventArgs e)
{
TSection Section;
/* Определение уровня выбранного элемента */ switch (Catalog_TV.SelectedNode.Level)
{
case 0:
/* Для каждого уровня требуется вывести свою
информацию и определить доступность действий */
51
Info_TB.Text = "Это корень дерева";
Add_B.Enabled = true; Change_B.Enabled = false; Del_B.Enabled = false; break;
case 1:
...; case 2:
...; case 3:
...; case 4:
...;
}
}
Внешний вид и пример работы программы показаны на рисунке 9.
Рисунок 9 – Внешний вид и пример работы программы (основная форма и диалоговые окна), реализующей работу с древовидной структурой
52