- •Общие требования
- •1 Примеры реализации заданий
- •1.1 Основные элементы класса
- •1.2 Перегрузка операторов
- •1.3 Использование делегатов
- •1.4 Универсальные типы библиотеки .Net Framework
- •2 Варианты заданий
- •2.1 Основные элементы класса
- •2.2 Перегрузка операторов
- •2.3 Использование делегатов
- •2.4 Универсальные типы библиотеки .Net Framework
1 Примеры реализации заданий
1.1 Основные элементы класса
Задание1: реализовать класс, хранящий информацию о складе. Склад состоит из бункеров одинаковой емкости, каждый из которых имеет свой текущий процент заполнения. Требования к реализации:
Обязательные параметры реализации класса и задания
обязательные поля:
1.уникальный номер склада. Не может быть изменен;
2.массив процентов заполнения бункеров. Количество бункеров задается в конструкторе класса и не может быть меньше 1. Количество бункеров не может быть изменено;
отображение: должен отображаться номер склада, а также процент заполнения каждого из бункеров;
обязательный метод класса: определение средней заполненности склада;
дополнительное действие в программе: определение бункера, имеющего максимальное заполнение. При выводе указать уникальный номер склада, номер бункера и процент его заполнения. Если есть несколько бункеров с максимальным заполнением, то вывести любой из них.
Для решения поставленной задачи на основной форме (Main_F) потребуются компоненты:
Storages_L класса Label для подписи компонента
Storages_LB;
Storages_LB класса ListBox для хранения списка складов;
Add_B класса Button для активизации добавления склада;
Change_B класса Button для активизации изменения параметров выбранного склада;
Del_B класса Button для активизации удаления выбранного скла-
да;
AverageFill_L класса Label для подписи компонента AverageFill_TB;
AverageFill_TB класса TextBox для вывода значения среднего заполнения выбранного склада;
MaxFill_L класса Label для подписи компонента MaxFill_TB;
MaxFill_TB класса TextBox для вывода информации бункере, имеющем максимальное заполнение;
1 Полные требования к выполнению задания приведены в общей части раздела
2.1
4
MaxFill_B класса Button для активизации поиска бункера с максимальным заполнением.
Установим следующие значения свойств компонентов (таблица 1):
Таблица 1 – Значения свойств компонентов основной формы для примера выполнения задания по работе с основными элементами класса
Компонент.Свойство |
Значение |
|
Storages_L.Text |
Список &складов |
|
Add_B.Text |
Д&обавить |
|
Change_B.Text |
Измен&ить |
|
Del_B.Text |
Уда&лить |
|
AverageFill_L.Text |
Среднее &значение заполнения |
|
выбранного склада |
||
|
||
AverageFill_TB.ReadOnly |
True |
|
|
|
|
MaxFill_L.Text |
Бункер, имеющий |
|
&максимальное заполнение |
||
|
||
MaxFill_TB.ReadOnly |
True |
|
|
|
|
MaxFill_B.Text |
На&йти |
Для решения поставленной задачи на диалоговом окне (Storage_F) потребуются компоненты:
Count_L класса Label для подписи компонента Count_NUD;
Count_NUD класса NumericUpDown для задания количества бункеров в складе;
Fill_L класса Label для подписи компонента Fill_DGV;
Fill_DGV класса DatagridView для ввода значений заполнения бункеров;
Ok_B класса Button для подтверждения ввода;
Cancel_B класса Button для отказа от ввода.
Установим следующие значения свойств компонентов (таблица 2):
Таблица 2 – Значения свойств компонентов диалогового окна для примера выполнения задания по работе с основными элементами класса
Компонент.Свойство |
Значение |
Count_L.Text |
Количество бун&керов |
Count_NUD.Minimum |
1 |
|
|
Count_NUD.Maximum |
10 |
|
|
Count_NUD.Modifiers |
Public |
|
|
Fill_L.Text |
Заполнение &бункеров, % |
Fill_DGV.AllowUserToAddRows |
False |
|
|
Fill_DGV.AllowUserToDeleteRows |
False |
|
|
5
Fill_DGV.ColumnHeadersVisible |
False |
|
|
Fill_DGV.RowHeadersVisible |
False |
|
|
Fill_DGV.Modifiers |
Public |
|
|
Ok_B.Text |
Ok |
Ok_B.DialogResult |
OK |
|
|
Cancel_B.Text |
&Отмена |
Cancel_B.DialogResult |
Cancel |
|
|
Для реализации класса (назовём его Storage) потребуется отдельный модуль. Добавим его в программу через меню «Проект → Добавить класс». Реализация членов класса приведена ниже.
class Storage
{
//Статическое поля для обеспечения уникальности номеров
//складов
static int _LastID;
private int _ID; // Уникальный номер склада private double[] _Bunkers; // Заполненность бункеров
//Конструктор, в качестве параметров которого задается
//количество бункеров
public Storage(int Count)
{
_ID = ++_LastID; // Заполнение номера склада
//Если количество бункеров задано неправильно, то оно
//корректируется на минимальное значение
_Bunkers = Count > 0 ? new double[Count] : new double[1];
}
//Конструктор без параметров, создающий склад с одним
//бункером и использует конструктор с параметром public Storage() : this(1) { }
//Переопределение метода отображения
public override string ToString()
{
string s = "Склад №" + _ID + ":";
for (int i = 0; i < _Bunkers.Length; i++)
s += string.Format(" {0}%", _Bunkers[i]); return s;
}
//Создание индексатора для корректного доступа к массиву
//заполненности бункеров
public double this[int Index]
{
get
{
// Если индекс задан не правильно, то возвращается -1 return Index >= 0 && Index < _Bunkers.Length ? _Bunkers[Index] : -1;
}
6
set
{
//Изменение значения производится, только если индекс и
//процент заполнения заданы корректно
if (Index >= 0 && Index < _Bunkers.Length &&
value >= 0 && value <= 100) _Bunkers[Index] = value;
}
}
//Свойство для получения количества бункеров public int Count
{
get { return _Bunkers.Length; }
}
//Свойство для получения уникального номера склада
public int ID
{
get { return _ID; }
}
// Метод расчета средней заполненности склада public double AverageFill()
{
double Sum = 0;
for (int i = 0; i < _Bunkers.Length; i++) Sum += _Bunkers[i];
return Sum / _Bunkers.Length;
}
}
Опишем событие ValueChanged компонента Count_NUD диалогового окна:
private void Count_NUD_ValueChanged(object sender, EventArgs e)
{
Fill_DGV.RowCount = Convert.ToInt32(Count_NUD.Value);
}
Опишем событие Load диалогового окна:
private void Storage_F_Load(object sender, EventArgs e)
{
//При загрузке формы устанавливаются начальные параметры
//компонента Fill_DGV
Fill_DGV.RowCount = Convert.ToInt32(Count_NUD.Value); Fill_DGV.ColumnCount = 1;
}
Опишем событие FormClosing компонента диалогового окна:
private void Storage_F_FormClosing(object sender, FormClosingEventArgs e)
7
{
if (DialogResult == DialogResult.OK)
{
int i = 0; // Номер проверяемого бункера try
{
for (i = 0; i < Fill_DGV.ColumnCount; i++)
{
//Проверка, что что-нибудь введено. Если ничего не
//введено, то при преобразовании получится ноль
if (Fill_DGV[0, i].Value == null)
{
Fill_DGV.Focus();
// Выбор ячейки, в которой не введено значение
Fill_DGV.CurrentCell = Fill_DGV[0, i]; throw new Exception(
"Не введено значение процента заполнения в " + (i + 1) + " бункере");
}
double Temp = Convert.ToDouble(Fill_DGV[0, i].Value);
// Проверка на допустимый диапазон if (Temp < 0 || Temp > 100)
{
Fill_DGV.Focus(); Fill_DGV.CurrentCell = Fill_DGV[0, i]; throw new Exception(
"Неправильное значение процента заполнения в " + (i + 1) +
" бункере. Процент заполнения должен быть от 0 до 100");
}
}
}
catch (FormatException)
{
e.Cancel = true; Fill_DGV.Focus();
Fill_DGV.CurrentCell = Fill_DGV[0, i];
//Отображение окна сообщения с нужным текстом, нужным
//заголовком, нужными кнопками и нужным рисунком
MessageBox.Show(
"Неправильное значение процента заполнения в " +
(i + 1) +
" бункере. Процент заполнения должен быть дробным числом", "Требуется исправление", MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
catch (Exception E)
{
e.Cancel = true;
MessageBox.Show(E.Message, "Требуется исправление", MessageBoxButtons.OK,
8
MessageBoxIcon.Warning);
}
}
}
При изменении состояния программы должны блокироваться или разблокироваться те или иные кнопки, а также подсчитываться среднее значение заполнения выделенного склада. Создадим для этого в классе основной формы отдельный метод1.
private void SetEnabledButtons()
{
Change_B.Enabled = Storages_LB.SelectedItem != null; Del_B.Enabled = Change_B.Enabled;
MaxFill_B.Enabled = Storages_LB.Items.Count > 0; if (Storages_LB.SelectedIndex >= 0)
{
Storage Temp = Storages_LB.SelectedItem as Storage; AverageFill_TB.Text = Temp.AverageFill().ToString();
}
else
AverageFill_TB.Text = "";
}
Опишем событие Click кнопки Add_B основной формы:
private void Add_B_Click(object sender, EventArgs e)
{
//Создание диалогового окна и настройка его свойств
Storage_F Dialog = new Storage_F(); Dialog.Text = "Добавление склада";
//Вызов диалогового окна и определение метода его закрытия
if (Dialog.ShowDialog() == DialogResult.OK)
{
// Создание объекта и заполнение его свойств
Storage Temp = new Storage(Dialog.Fill_DGV.RowCount); for (int i = 0; i < Dialog.Fill_DGV.RowCount; i++)
Temp[i] = Convert.ToDouble(Dialog.Fill_DGV[0, i].Value); Storages_LB.Items.Add(Temp);
//Установка доступности кнопок
SetEnabledButtons();
//Так как добавлен новый объект, то результат поиска
//бункера с максимальным заполнением может быть неверным.
//Очистка старого результата
MaxFill_TB.Text = "";
1 Такой способ не оптимален с точки зрения производительности, т.к. возможны повторные действия с неизмененными данными. Но он позволяет сосредоточить все управление блокировкой кнопок в одном месте и легко модернизировать программу
9
}
}
Опишем событие Click кнопки Change_B основной формы:
private void Change_B_Click(object sender, EventArgs e)
{
// Дополнительная проверка, что какой-нибудь склад выбран if (Storages_LB.SelectedIndex >= 0)
{
Storage_F Dialog = new Storage_F(); Dialog.Text = "Изменение параметров склада";
Storage Temp = Storages_LB.SelectedItem as Storage; Dialog.Count_NUD.Value = Temp.Count;
//Установка параметров компонента Fill_DGV. Необходима,
//т.к. событие Load диалогового окна к этому моменту еще
//не выполнено, но требуется заполнение ячеек компонента
Dialog.Fill_DGV.RowCount = Temp.Count; Dialog.Fill_DGV.ColumnCount = 1;
for (int i = 0; i < Temp.Count; i++) Dialog.Fill_DGV[0, i].Value = Temp[i];
// Запрет изменения количества бункеров
Dialog.Count_NUD.Enabled = false;
if (Dialog.ShowDialog() == DialogResult.OK)
{
for (int i = 0; i < Dialog.Fill_DGV.RowCount; i++) Temp[i] = Convert.ToDouble(
Dialog.Fill_DGV[0, i].Value); Storages_LB.Items[Storages_LB.SelectedIndex] = Temp; SetEnabledButtons();
MaxFill_TB.Text = "";
}
}
else MessageBox.Show(
"Не выбран склад для изменения параметров", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Опишем событие Click кнопки Del_B основной формы:
private void Del_B_Click(object sender, EventArgs e)
{
if (Storages_LB.SelectedIndex >= 0)
{
//Реализация подтверждения удаления данных. Ниже показано
//использование метода MessageBox.Show с отображением на
//окне нужных кнопок и проверкой, какая из кнопок была
//нажата
if (MessageBox.Show(
"Вы действительно хотите удалить выбранный склад?",
10
"Подтверждение", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
{
Storages_LB.Items.RemoveAt(Storages_LB.SelectedIndex); SetEnabledButtons();
MaxFill_TB.Text = "";
}
}
else MessageBox.Show(
"Не выбран склад для изменения параметров", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Опишем событие SelectedIndexChanged компонента Storages_LB основной формы:
private void Storages_LB_SelectedIndexChanged( object sender, EventArgs e)
{
//При изменении выбора склада необходимо обновить
//доступность кнопок и заполненность выбранного склада
SetEnabledButtons();
}
Опишем событие Click кнопки MaxFill_B основной формы:
private void MaxFill_B_Click(object sender, EventArgs e)
{
if (Storages_LB.Items.Count > 0)
{
//Описание переменных для хранения номера склада и
//номера бункера
int MaxIndexStorage = 0, MaxIndexBunker = 0;
//Описание переменной для хранения значения максимальной
//загруженности бункера. В качестве начального значения
//берется значение первого бункера первого склада
double MaxFill = (Storages_LB.Items[0] as Storage)[0]; for (int i = 0; i < Storages_LB.Items.Count; i++)
{
Storage Temp = Storages_LB.Items[i] as Storage; for (int j = 0; j <= Temp.Count; j++)
if (Temp[j] > MaxFill)
{
MaxFill = Temp[j]; MaxIndexStorage = Temp.ID; MaxIndexBunker = j;
}
}
MaxFill_TB.Text = string.Format(
"Склад №{0}, бункер {1}, заполнение {2}%",
11
MaxIndexStorage, MaxIndexBunker + 1, MaxFill);
}
else MessageBox.Show(
"Не введены данные хотя бы по одному складу", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Опишем событие Load диалогового окна:
private void Main_F_Load(object sender, EventArgs e)
{
//При загрузке основной формы установим начальное состояние
//доступности кнопок
SetEnabledButtons();
}
Внешний вид и пример работы программы показаны на рисунке 1.
12