Средства управления работой программы
Добавим на нашу форму кнопку выбора (CheckBox) и две радиокнопки (RadioButton). Напомним, что все кнопки выбора независимы друг от друга. Радиокнопки обычно объединяют в радиогруппы и из каждой группы в любой момент времени может быть выбрана одна и только одна радиокнопка.
Пусть наша единственная кнопка выбора имеет имя cB1 и показанное на рис. 4.1 значение свойства Text. Назначение этой кнопки: вычисления возможны лишь в случае, если она выбрана (свойство Checked имеет значение True).
Для создания радиогруппы необходимо сначала занести на форму компонент рамка GroupBox (находится среди элементов управления Containers) и лишь после этого на него требуемое количество (в нашем случае 2) радиокнопок. Пусть свойство Text для GroupBox имеет значение Order, свойство Name сохраняет значение по умолчанию. Для двух радиокнопок дадим свойству Name значения rB1 и rB2 соответственно. Значения их свойств Text видны на рис. 4.1. В нашем случае от выбора радиокнопки зависит очередность соединения введенных строк.
Поменяем реализацию двух командных кнопок:
private void button1_Click(object sender, EventArgs e)
{ // сцепление введенных строк Concat
if (rB1.Checked)
label5.Text = textBox1.Text + textBox2.Text;
if(rB2.Checked)
label5.Text = textBox2.Text + textBox1.Text;
}
private void button2_Click(object sender, EventArgs e)
{ // вычисления Compute
int i, j, k;
if (cB1.Checked)
{
i = Convert.ToInt32(textBox1.Text);
j = Convert.ToInt32(textBox2.Text);
k = 2 * i + 5 * j;
label6.Text = Convert.ToString(k);
// label6.Text = "" + k;
}
else MessageBox.Show("Режим вычислений не установлен ");
// таким образом можно вывести сообщения пользователю
}
Создание меню
Для создания меню перенесем на форму компонент MenuStrip, который находится в группе компонентов Menus & Toolbars. Местоположение его на форме значения не имеет, поскольку меню всегда находится на одном и том же месте. После этого двигаясь с помощью мыши по пунктам меню набираем на клавиатуре их названия, которые автоматически становятся значениями свойств Text. Значения свойств Name выбирают по умолчанию, например, пункт меню File получит имя fileToolStripMenuItem. Если не предполагается в дальнейшем ссылка в функциях на пункты меню, то имена, естественно, можно такими и оставить. В противном случае желательно их поменять на нечто покороче. Например, делать их равными свойству Text.
Для внесения исправлений в уже созданное меню поставим курсор на тот пункт (неважно, горизонтального или выпадающего меню) перед которым необходимо вставить новый пункт, нажмем на правую клавишу и выберем пункт Insert. Для удаления поставим курсор на удаляемый пункт и выберем из выпадающего меню пункт Delete. Для изменения свойств выделяем пункт меню и пользуемся традиционным способом –списком свойств.
Для реализации пунктов меню ставим на него курсор, делаем двойной щелчок и в полученную заготовку функции пишем необходимую программу.
4.4. Ввод/вывод массивов
Рассмотрим ввод/вывод массивов на примере формы на рис.4.2. Одномерный массив может быть представлен как в виде строки, так и в виде столбца. В обоих случаях используется знакомый нам компонент TextBox, но для представления массива столбцом необходимо свойству Multiline придать значение True. После этого можно «вытянуть» этот компонент по вертикали. Для представления двумерного массива используем этот же компонент, Multiline имеет значение True, а компоненту дадим необходимые для размещения массива высоту и ширину. Дадим компонентам следующие имена (свойство Name): mas_row для массива-строки, mas_col для массива столбца, mas22 - для двумерного массива, result – для результата. Тип данных в компонентах TextBox по прежнему String.
Рис. 4.2
Назначение кнопок видно из названий.
4.4.1. Ввод/вывод и обработка одномерного массива-строки
Для ввода одномерного массива – строки необходимо определить, какой разделитель будет использован между отдельными элементами. В нашем случае используем знак ; . Реализация кнопки «Массив – строка» приведена ниже:
private void button5_Click(object sender, EventArgs e)
{
string[] temp;
//массив для размещения вводимых и выводимых данных
int k, pr = 1;
string dan;
dan = mas_row.Text;
//присвоение набранной строки целиком переменной
temp = dan.Split(';');
// выделение отдельных элементов массива, аргументом функции
// Split является наш разделитель ;
k = temp.Length; //определим длину введенного массива
while (temp[k - 1] == "") k--; // см. разъяснение 1
int[] x = new int[k];
//объявление массива чисел для введенных данных
for (int i = 0; i < k; i++)
//преобразование типов введенных данных
x[i] = Convert.ToInt32(temp[i]);
for (int i = 0; i < k; i++)
{ // обработка введенного массива
x[i] = x[i] * x[i];
pr *= x[i];
}
rezult.Text = "Proizv " + pr; // вывод результата
dan = "";
mas_row.Clear(); // очистка поля mas_row для вывода
for (int i = 0; i < k; i++)
dan += " " + x[i];
// накопление полученных элементов числового массива в
// переменной символьного типа, в качестве разделителя – пробел
mas_row.Text = dan; //вывод результата
}
Разъяснение 1. Если закончить последовательность вводимых данных разделителем (в нашем случае ;), то последним элементом массива temp будет пустая строка, которая не может быть преобразована в число. Поэтому исключим эту возможность. Если при вводе ставить два разделителя подряд, то в массиве temp будет пустая строка в середине. Что с ней делать – решать программисту!
4.4.2. Ввод/вывод и обработка одномерного массива-столбца
При вводе одномерного массива в виде столбца необходимо просто набрать значения, нажав после каждого на Enter. Нажатие на Enter после последнего значения вставит пустую строку в качестве последнего элемента. Реализация кнопки «Массив – столбец»:
private void button4_Click(object sender, EventArgs e)
{
string []st1;
int []mas;
//массивы для размещения данных
int k,pr=0;
st1=new string[mas_col.Lines.Length];
k=mas_col.Lines.Length;
mas = new int[k];
//инициируем массивы для принятия исходных данных, количество
//элементов равно количеству строк в компоненте mas_col
st1 = mas_col.Lines;
//перенесем введенный массив из компонента mas_col в массив st1
while(st1[k-1]=="") k--; //см. разъяснение 1 выше
for(int i=0;i<k;i++) // преобразование типов данных
mas[i]=Convert.ToInt32(st1[i]);
for (int i = 0; i < k; i++)
{ // обработка массива
mas[i] = 5 * mas[i];
pr += mas[i];
st1[i] = Convert.ToString(mas[i]);
// преобразование типов данных для вывода
}
mas_col.Clear(); //очистка поля вывода
mas_col.Lines = st1; // вывод результата: массива - столбца
rezult.Text="Summa Col "+pr;
}
4.4.3. Ввод/вывод и обработка двумерного массива
Перед тем как приступить к вводу/выводу и обработке двумерного массива введем некоторые уточнения. Очевидно, что на кнопку «Обработка и вывод двумерного массива» нет смысла нажать пока массив не введен. Поэтому изначально пусть эта кнопка будет «серой», для чего на этапе проектирования дадим ее свойству Enabled значение False. Во-вторых, ввод и обработка двумерного массива будут в разных функциях, поэтому его необходимо объявить как переменную класса Form1 (Напомним, что каждой форме соответствует класс). Найдем раздел переменных этого класса и запишем туда:
private double[,] a;
int n, m; //количество строк и столбцов
Мы по существу уже знаем, как ввести двумерный массив: он представляет собой столбец с одномерными массивами - строками. Используем в качестве разделителя ; . Предположим, что двумерный массив прямоугольный.
Реализация кнопки «Ввод двумерного массива»:
private void button1_Click(object sender, EventArgs e)
{
string[] mas; // массив для представления одной вводимой строки
string s = "";
string[] dan; //массив для представление всех введенных строк
this.button2.Enabled = true; // кнопка обработки откроется
n = mas22.Lines.Length; //количество строк в двумерном
// массиве будет равно количеству введенных строк
dan = new string[n];
dan = mas22.Lines; //введенные строки передаем
// массив символьных строк, одна строка – один элемент
while (dan[n - 1] == "") n--;
mas = dan[0].Split(';'); //разделим первую строку на
//элементы с помощью разделителя
m = mas.Length; // определим количество столбцов двумерного
// массива
a = new double[n, m]; // инициализация двумерного массива
for (int i = 0; i < n; i++)
{ // строка за строкой преобразуем типы данных и
// формируем числовой массив
mas = dan[i].Split(';');
for (int j = 0; j < mas.Length; j++)
a[i, j] = Convert.ToDouble(mas[j]);
} }
Реализация кнопки «Обработка и вывод двумерного массива»:
private void button2_Click(object sender, EventArgs e)
{
string[] st1 = new string[n]; // массив для
// накопления двумерного массива после обработки
double smm=0;
mas22.Clear(); //очистка поля для вывода
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{ // обработка массива
a[i, j] = 2 * a[i, j];
smm += a[i, j];
}
// цикл подготовки двумерного массива к выводу
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
st1[i]+=" "+Convert.ToString(a[i,j]);
mas22.Lines = st1; // вывод двумерного массива
rezult.Text = "Summa 2: "+Convert.ToString(smm);
}
Примечание. На рис. 4.1. форма показана после нажатия кнопок «Ввод двумерного массива» и «Обработка и вывод двумерного массива»
4.4.4. Форматированный ввод/вывод двумерного массива
Приведенные выше примеры ввода массивов легки в реализации, но требуют от пользователя большой аккуратности при наборе данных. Имеется и возможность форматированного ввода/вывода массивов. Ограничимся рассмотрением двумерного массива, упростить приводимый пример для одномерного случая не составляет труда. Рассмотрим реализацию формы, приведенной на рис. 4.3. Кроме знакомых нам компонентов занесем на форму компонент DataGridView из группы Data и дадим ему имя Gr1. Этот компонент служит для представления таблицы (по сути двумерного массива) на форме. Для внутреннего представления двумерного массива объявим потомок стандартного класса DataTable и уточним его свойства.
Рис. 4.3
Разрешается кроме класса Form1, который создается автоматический, иметь и собственные классы, но их объявления должны всегда быть послеForm1. Так поступим и мы: класс Dt, потомок DataTable имеется в конце. Ничего нового мы в потомок не добавим, кроме конструктора, который должен передать единственный параметр конструктору класса – предка.
В состав класса Form1 добавим функцию InitGrid с двумя параметрами: количество строк и количество столбцов. Эта функция определяет свойства создаваемой таблицы и связывает ее с представлением на форме. Для начальной инициализации таблицы включим ее вызов в конструктор класса Form1.
namespace WA1
{
public partial class Form1 : Form
{
Dt Tabel;
void InitGrid(int n, int m)
{
Tabel = new Dt();
DataColumn x2 = Tabel.Columns.Add("First", typeof(Int32));
// создание первого столбца, параметры: заглавие и тип данных
DataColumn x1;
for (int i = 0; i < m; i++)
{ //создание остальных столбцов, параметры те же
x1 = Tabel.Columns.Add("Col " + (i + 1), typeof(Int32));
x1.DefaultValue = 0; // значение по умолчанию
}
for (int i = 0; i < n; i++)
{ //создание срок
DataRow y = Tabel.NewRow();
Tabel.Rows.Add(y);
Tabel.Rows[i][0] = i;
// номера строк в записываютсяпервый столбец
}
x2.ReadOnly = true; // первый столбец для номеров строк, туда
// нельзя ввести данные
Gr1.DataSource = Tabel;// установим связь между внутренним и
// внешним представлениями таблиц
}
public Form1()
{ // конструктор Form1
InitializeComponent();
InitGrid(3, 4); //создание начальной таблицы
}
private void In1_Click(object sender, EventArgs e)
{ // изменение количества строк и столбцов
int k,n;
k = Convert.ToInt32(textBox1.Text); //Количество строк
n = Convert.ToInt32(textBox2.Text); //Количество столбцов
InitGrid(k, n);
}
private void First_Click(object sender, EventArgs e)
{ //обработка данных из таблицы, результат - число
int sum = 0;
for (int i = 0; i < Tabel.Rows.Count ; i++)
for (int j = 1; j < Tabel.Columns.Count; j++)
sum += Convert.ToInt32(Tabel.Rows[i][j]);
rezult.Text=Convert.ToString(sum);
}
private void Second_Click(object sender, EventArgs e)
{ // обработка таблицы, результат - массив
int y,z = 3;
for (int i = 0; i < Tabel.Rows.Count ; i++)
for (int j = 1; j < Tabel.Columns.Count; j++)
{
y = Convert.ToInt32(Tabel.Rows[i][j]);
y += z;
Tabel.Rows[i][j] = Convert.ToString(y);
}
}
private void button1_Click(object sender, EventArgs e)
{
Close();
}
}
class Dt : DataTable
{//класс для внутреннего представления таблицы
public Dt() : base("Table") { } //Dt конструктор
} }
Примечания.
- Нумерация строк и столбцов начинается с нуля. Нулевой столбец мы используем для номеров строк, поэтому при обработке минимальное значение номеров столбцов равно единице, а номеров строк – нулю. Первая строка считается стандартной и она в нумерацию не входит.
- Компонент DataGridView предназначен и для представления данных из баз данных (реляционных таблиц), этим и объясняется необходимость указывать для каждого столбца тип данных. Явные преобразования типов данных тем не менее обязательны!
- На рис. 4.3. форма показана после нажатия кнопки «Сумма».