Лекція 1. Проектування візуального додатку в C#

 

Почнемо зі створення порожнього додатка і подивимося, що для нас згенерує майстер Visual Studio, щоб на екрані з'явилося вікно програми, і з чого все це складається. Для створення проекту вибираємо в меню File | New | Project і у вікні вибираємо Windows Forms Application в розділі мови програмування Visual C # | Windows (рис. 1) Назвемо своє новий додаток OurFirstVisualApplication.

Давайте подивимося, які модулі додані в рішення. Їх всього два - Forml.cs (цей модуль складається з декількох файлів) і Program.cs. Почнемо з другого файлу, тому що саме з нього починається виконання програми і там знаходиться метод Main (). Код файлу ви можете побачити в лістингу 1.

Лістинг 1. Вміст файлу Program.cs

using System;

using System.Collections.Generic; using System.Windows.Forms;

namespace OurFirstVisualApplication {

static class Program {

[STAThread] static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Forml());

}

}

}

 

Описание: C:\!!C#\media\image1.jpeg

 

Рис. 1. Вікно створення нового проекту (виділено пункт для створення візуального додатка)

Щоб заощадити місце, приберемо коментарі, але в них всього лише було написано, що перед нами вхідна точка виконання. А ми вже й без коментарів знаємо, що метод Main () завжди викликається першим під час запуску програми. Але давайте все по порядку.

Файл Program.es потрібен тільки як заглушка, в якій оголошено клас з методом Main (). Він не несе в собі ніякої логіки, крім створення програми та відображення головного вікна програми. Частіше за все в цей файл ви заглядати не будете, але знати про його існування бажано.

1.1.      Простір імен

На самому початку файл Program.cs підключає три простори імен, з якими буде відбуватися робота. Насправді для компіляції програми досить тільки двох просторів - першого і третього. Друге місце не потрібно і в даному коді не використовується, тому ми не будемо його поки розглядати. Даний простір імен відноситься до колекцій.

З необхідних залишаються два простори імен:

+ System- ми підключали цей простір імен для всіх додатків, які писали до сих пір, а точніше, майстер підключав його замість нас. У цьому просторі в .NET оголошені основні типи даних і все, без чого не виживе ні один додаток .NET, який хоч щось робить;

+ System.windows.Forms- в цьому просторі імен розміщено все, що необхідно для функціонування форми. Формами в .NET називають проект майбутнього вікна. Якщо клас - це специфікація, по якій створюється об'єкт, то форма-це специфікація, по якій створюється вікно. Ми плануємо працювати з візуальним інтерфейсом, тому даний простір імен просто необхідний.

Як дізнатися, які простори імен підключати, а які не потрібно? Тут може допомогти файл допомоги і MSDN, де при описі кожного класу, методу або властивості обов'язково вказується, в якому просторі імен його можна знайти. Відкрийте файл допомоги (команда меню Help | Index (Допомога | Індекс)) і введіть в рядок пошуку Look for (Шукати) зліва: Application class. Клацніть двічі по знайденому імені, і відкриється сторінка допомоги за даним класу (рис. 2).

На рис. 2 я виділив той фрагмент, де якраз і написано, в якому просторі імен знаходяться опис та збірки (dll-файл) з реалізацією класу. Нас більше цікавить саме простір імен, а не збірка. Мені жодного разу не доводилося використовувати файл збірки, принаймні цей. Файл зборки може стати в нагоді, якщо ви використовуєте щось специфічне. Всі основні файли додаються в розділ References проекту автоматично при створенні проекту. Якщо ви будете використовувати щось специфічне, то спочатку слід під'єднати потрібний файл збірки самостійно.

Другий метод дізнатися простір імен - не думати про нього, а покласти всю головний біль на середовище розробки. У Visual Studio голова досить хороша, і вона з легкістю вирішить таку задачу.

Спробуйте зараз ввести десь У коді методу Main () слово OleDbConnection. Це клас, який використовується для з'єднання з базами даних, і компілятор не знайде його серед підключених просторів імен і звичайно ж підкреслить. Тепер ви можете натиснути правою кнопкою по підкресленому імені, в контекстному меню розкрити пункт Resolve (Отримати), і в його підменю будуть перераховані простори імен, в яких середовище розробки змогла знайти вказане слово (рис. 3).

Описание: C:\!!C#\media\image2.jpeg

Рис. 2. Файл допомоги по класу Application

У контекстному меню доступні два варіанти вирішення проблеми, між якими буде знаходитися роздільник. Вище роздільника будуть варіанти, які додають в початок модуля коду using з обраним простором імен. Варіанти нижче роздільника змінюють коротку назву методу на повне. Тобто у випадку з типом даних oleDbConnection, якщо ви виберете варіант нижче роздільника, то тип даних заміниться на System.Data.OleDb.OleDbConnection. Якщо ВИ знаєте, що це єдине звернення до цього типу даних, то можна використовувати повний шлях, але якщо в модулі коду ви будете використовувати цей тип даних багато разів, то простіше буде відразу додати його в розділ using.

Частіше за все в цьому підменю буде тільки один варіант як до роздільника, так і після, але деякі імена можуть бути оголошені як для Windows, так і для Web. У таких випадках потрібно вибрати потрібну збірку. Це не складно, тому що для Інтернету найчастіше використовується простір імен System.web. Наприклад, клас Application для інтернет-програмування знаходиться в Microsoft .Web. Administration. Ось воно ключове слово "Web", яке знаходиться в середині.

Описание: C:\!!C#\media\image3.jpeg

Рис. 3. Контекстне меню дозволяє вирішити проблему підключення просторів імен

Простір імен за замовчуванням для вашого проекту можна змінити. Для цього клацніть правою кнопкою миші по імені проекту і виберіть в контекстному меню пункт Properties, щоб змінити властивості проекту. Тут в розділі Application в поле Default namespace (Простір імен за замовчуванням) ви можете змінити ім'я простору імен. При цьому вже існуючий код залишиться в старому просторі імен. Існуючий код змінюватися автоматично не буде, а ось нові файли, які будуть додаватися до проекту, будуть потрапляти вже в новий простір. Якщо вам потрібно перенести існуючий код в новий простір, то потрібно буде зробити це руками, змінюючи поточний простір імен на новий. Можна залишити і старе ім'я, тому що в одній збірці можуть бути і два, і три різних простори імен, якщо вас це влаштовує.

1.2.      Потоки

Зверніть увагу, що перед методом Main () в квадратних дужках стоїть ключове слово STAThread. Воно вказує на те, що модель потоків для додатка буде поодинока. Такий атрибут повинен бути вказаний для всіх точок входу в WinForms-додатка. Якщо він буде відсутній, то компоненти Windows можуть працювати некоректно.

Без атрибуту STAThread додаток буде використовувати многопоточную модель поділу, яка не підтримуються для Windows Forms. Множинність потоків підтримується, але STAThread - це модель поділу коду (multi-threaded apartment model).

1.3.         Клас Application

У лістингу 1 в методі Main () усі рядки коду є зверненням до класу Application, який надає статичні властивості і методи (це означає, що не потрібно створювати екземпляр класу, щоб їх викликати) для підтримки роботи додатку. Основними методами є запуск і зупинка додатка, а також обробка повідомлень Windows. При виникненні будь-яких ситуацій ОС відправляє вікну подію, і вікно повинно опрацювати цю подію. Наприклад, якщо користувач натиснув на кнопку закриття вікна, то цьому вікну направляється подія WM_CLOSE. Зловивши цю подію, вікно повинно відреагувати, звільнити ресурси і приготуватися до знищення. Будь-яка повкдінка користувача, включаючи натискання клавіш на клавіатурі і рух курсору миші, обробляє ОС, а потім за допомогою повідомлень відправляє зміни в додаток.

Щоб відловлювати повідомлення, які надсилає додатку операційна система, в додатку повинен бути запущений цикл. У таких мовах, як C / C ++, цикл отримує від ОС повідомлення, обробляє його і чекає наступного повідомлення. Цей цикл триває доти, поки не відбудеться вихід з додатку.

Клас Application бере на себе всю відповідальність за отримання повідомлень від системи і перенаправлення їх у вікна, щоб ви могли обробити їх. Трохи пізніше ми навчимося ловити повідомлення, а поки нам потрібно знати, що за підготовку повідомлення для обробки відповідає саме клас Application.

Розглянемо методи, які викликаються в класі, який згенерував нам майстер Visual Studio. Перший метод класу Application, який ми викликаємо - EnabieVisualStyles (). Цей метод включає відображення в стилях ОС, на якій запущено програму. Якщо видалити цей рядок і запустити програму, то всі елементи управління будуть виглядати в стилі Windows 9х з квадратними кутами навіть в Windows Vista. Не бачу сенсу повертатися в доісторичні часи візуального інтерфейсу, але якщо вам раптом це знадобиться, тепер ви знаєте, який рядок потрібно видалити.

Наступний метод додатка, який викликає програма - SetCompatibleTextRenderingDefault () Деякі елементи управління можуть відображати текст за допомогою старих функцій GDI або за допомогою нових функцій GDI +. Якщо методом SetCompatibleTextRenderingDefault () передати Значення false, то будуть використовуватися функції GDI +.

Це все були підготовчі методи, а останній метод Run () є найбільш важливим. Цей метод запускає прихований цикл обробки повідомлень ОС і робить видимою форму, яка передається в якості параметра. Як параметр в нашому прикладі передається ініціалізація об'єкта класу Form1, і для цього викликається конструктор класу за допомогою оператора new. Просто ми завжди присвоювали результат виконання new змінній, а в цьому випадку нам змінна не потрібна, і ми більше не будемо використовувати об'єкт в методі Main (), тому, ніде нічого не зберігаючи, відразу передаємо новий об'єкт методу. Те ж саме можна було написати так:

Form1 form - new Forml();

Application.Run(form);

2.    Нащадок Form для головної форми

Тепер подивимося на вміст файлу Form.css. Якщо розкрити гілку форми, то ви побачите, що там є ще два файли: Forml.Designer.сs і Form.resx. Виходить, що форма описана аж в трьох файлах? Так і є. Звичайно ж, все можна було реалізувати в одному файлі з кодом, але розбиття зроблено для вашої ж зручності.

2.1.      Ресурси програми

У resx-файлі зберігаються атрибути файлу коду, і з ним працює середовище розробки. Мені поки що жодного разу не доводилося редагувати його безпосередньо, в основному я робив це з середовища розробки. Пам'ятайте, що там середовище розробки зберігає параметри форми для внутрішнього використання і ресурси програми.

Але є глобальний файл ресурсів, з яким ви можете працювати без проблем. Він знаходиться в папці Properties проекту і називається Resources.resx. У ньому розташовані ресурси програми, і вони можуть бути доступні будь-якій формі проекту.

Ви можете створювати в файлі resx ресурси, такі як рядки, зображення і т. д., Які в подальшому можна буде використовувати в програмі.

Спробуйте клацнути двічі по файлу Forml.resx в панелі Solution Explorer. Перед вами відкриється редактор ресурсів форми (рис. 4).

Описание: C:\!!C#\media\image4.jpeg

Рис. 4. Окно редактирования ресурсов формы

В панелі інструментів редактора ресурсів заголовок першої кнопки вказує на той модуль, який зараз відкритий. На рис. 4 відкритий модуль редагування рядків (кнопка називається Strings). Якщо клацнути стрілку вниз праворуч від кнопки Strings, то з'явиться спливаюче меню, в якому ви можете вибрати тип ресурсів, які можна редагувати. Існують наступні типи ресурсів (в дужках вказані гарячі клавіші для виклику відповідного модуля редагування):

+ Strings (<Ctrl> + <1>) - рядки;

+ Images (<Ctrl> + <2>) - зображення;

+ Icons (<Ctrl> + <3>) - іконки;

+ Audio (<Ctrl> + <4>) - аудіозаписи;

+ Files (<Ctrl> + <5>) - файли;

+ Other (<Ctrl> + <6>) - щось інше, наприклад, призначені для користувача дані.

Для додавання нового ресурсу такого ж типу, як і відкритий модуль, досить клацнути по кнопці Add Resource (Додати ресурс) на панелі інструментів-тов. Щоб вибрати тип ресурсу і метод створення, клацніть по стрілці вниз праворуч від кнопки Add Resource. У випадаючому меню можна вибрати створення ресурсу на основі існуючого файлу або зробити вибір типу зображення для ресурсу типу Image.

2.2.      Файл для логіки модуля

Тепер подивимося на вміст файлу Form.css. Якщо двічі клацнути по ньому, то файл відкриється в режимі візуального дизайну, де ви можете розставляти компоненти. Щоб побачити код форми, потрібно натиснути клавішу <F7> або натиснути правою кнопкою миші на ім'я файлу в панелі Solution Explorer і з контекстного меню вибрати View Code (Показати код).

На самому початку файлу як завжди знаходиться підключення просторів імен, які ми можемо використовувати в модулі. Майстер підключив простори імен з великим запасом, тому що для компіляції коду, який знаходиться зараз в модулі, досить тільки system і System.windows .Forms. Все інше додано, бо в Microsoft порахували, що воно вам знадобиться.

Простори імен я опустив, а все інше показано в наступному коді:

namespace OurFirstVisualApplication

{

public partial class Forml : Form {

public Form1()

{

initializeComponent();

}

}

}

Відразу ж бачимо, що весь код також оголошений в просторі імен OurFirstvisuaiApplication. Усередині цього простору оголошується відкритий клас з ім'ям Form1, який є спадкоємцем класу Form. В цьому оголошенні багато чого цікавого, що ми ще не розглядали.

Для початку потрібно сказати про клас Form. В .NET цей клас реалізує усі необхідні для форми властивості і методи. Можна створити екземпляр цього класу і викликати метод відображення, і ви на екрані побачите вікно. Згадайте, що екземпляр класу форми був переданий методу Run () класу Application. Цей метод запускає цикл обробки і відображає вікно, так що нам відображати його не потрібно. Якщо ви будете створювати вікно самі, то його потрібно буде самому і відображати з допомогою методу Show () АБО ShowDialog (). Такі методи є у класі Form.

В даному випадку у нас не просто екземпляр класу, а його спадкоємець. Просто примірника було б достатньо, якби ми просто змінили його властивості і відобразили. Але чим може бути корисно порожнє вікно? Нічим! Тому ми створюємо спадкоємця і будемо розширювати його можливості, додаючи меню, кнопки і панелі, а не просто змінювати властивості.

В принципі, створити форму і накласти на неї компоненти можна і без наслідування, але мені здається, що такий підхід буде не дуже зручним і ефективним. Клас повинен бути автономним і має сам розставляти на поверхні всі необхідні компоненти. Те, що ми можемо поставити компоненти ззовні, не означає, що це хороший спосіб. При проектуванні класу завжди намагайтеся робити його автономним і максимально незалежним від зовнішніх факторів.

Дуже цікавим модифікатором на початку оголошення класу є partial. Він означає, що оголошення класу розбите на кілька файлів з кодом. Перед нами перший з цих файлів, а забігаючи вперед, скажу, що продовження реалізації класу знаходиться в файлі Form1.Designer.cs. Це дуже потужна можливість, коли ви можете розбити реалізацію класу на кілька файлів. Наприклад, в одному файлі ви реалізуєте усі методи, в іншому - усі властивості, а в третьому оголошуєте додаткові змінні. Для цього потрібно, щоб у всіх трьох файлах було оголошення класу з одним і тим же ім'ям і з модифікатором partial.

Усередині класу в файлі Form1.cs визначається тільки конструктор, в якому викликається метод Initializecomponent (). Що це таке, і звідки взявся цей метод? У ньому ініціалізувалися усі властивості форми і компоненти, які можуть бути встановлені на формі. Але де він оголошений і як виглядає? Про це ми дізнаємося в розд. 2.4.

2.3.      Іменування форми

Ми вже говорили, що всі змінні слід назвати зрозумілими словами. Ніяких імен в стилі Form1 в реальних додатках не повинно бути. Але не можна перейменовувати просто так змінну класу, особливо, якщо це форма. Тут краще перейменовувати файл.

Клацніть правою кнопкою миші по імені файлу форми в панелі Solution Ex-plorer і з контекстного меню виберіть пункт Rename (Перейменувати). Введіть нове ім'я форми, і будуть перейменовані не тільки імена файлів, пов'язаних з формою, а й клас, що знаходиться всередині. При цьому зміни відбудуться у всіх файлах, де задіяна форма, в тому числі і в файлі Program.cs.

2.4.      Код, згенерований дизайнером

Раніше весь код, який стосувався форми, знаходився в одному файлі коду. Але це було незручно, тому що розмір файлу ріс з божевільною швидкістю, і управління ним ставало незручним. Зараз середовище розробки розбиває код на два файли. В одному файлі ми пишемо всю свою логіку (в файлі Form1.cs, який ми розглянули в розд. 2.2), а в іншому файлі середовище розробки зберігає весь необхідний код для реалізації того, що ми зробимо візуально в дизайнері.

Ми поки нічого не робили в дизайнері, але давайте подивимося, що вже є в файлі Forml.Designer.cs. Для цього клацніть по ньому правою кнопкою миші і з контекстного меню виберіть пункт View Code. Код того, що згенерував дизайнер в моєму випадку, показаний в лістингу 2.

Лістинг 2. Код файлу Form1.Designer.cs

namespace OurFirstVisualApplication

{

partial class Form1 {

III <summary>

/// Required designer variable.

/// Переменные, необходимые дизайнеру /// </summary>

private System.ComponentModel.IContainer components = null;

/// <summary>

/// Clean up any resources being used.

/// Очистка любых использованных ресурсов /// </summary>

/// <param name="disposing'^true if managed resources should /// be disposed; otherwise, false.</param> protected override void Dispose(bool disposing)

{

if (disposing && (components null))

{

components.Dispose(); // уничтожить переменную компонентов

}

base.Dispose(disposing); // вызвать метод базового класса

}

#region Windows Form Designer generated code /// <summary>

/// Required method for Designer support - do not modify /// the contents of this method with the code editor.

/// Метод, который необходим дизайнеру - не изменяйте /// содержимое метода в редакторе кода /// < /summary>

private void InitializeComponent()

{

this.SuspendLayout();

//

// Form1 //

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

this.AutoScaleMode - System.Windows.Forms.AutoScaleMode.Font;

this.ClientSize = new System.Drawing.Size(284, 264);

this.Name = "Forml";

this.Text = "Forml";

this.ResumeLayout(false);

}

ftendregion

}

}

У цьому файлі немає ніяких підключень просторів імен, тому що весь код у файлі пишеться дизайнером автоматично, і ми сюди будемо заглядати дуже рідко, а редагувати його ще рідше. Дизайнер досить інтелектуальний, тому щоб нічого не підключати, він просто буде звертатися до всіх методів і типів даних по повному імені із зазначенням повного шляху в просторі імен.

Отже, в файлі Form.Designer.cs йде продовження оголошення класу Form1. Про це свідчить те, що на самому початку знову йде оголошення класу Form1 і вказано модифікатор partial. Тобто все, що буде описано в класі цього модуля, буде додано до конструктора, який ми вже розглянули в розд. 2.2.

На самому початку класу оголошується змінна components, яка є контейнером для всіх компонентів, які не мають візуального інтерфейсу, т. е. Не видимі на формі. Так, бувають і такі компоненти, і вони вбудовані в .NET у вигляді компонентів для зручності програмування.

Далі йде метод Dispose (), який буде викликатися системою, коли необхідно буде знищити об'єкт класу форми. У загальних рисах скажу, що відбувається в цьому методі, - викликається метод Dispose () змінної components, щоб вона почистила за собою, і викликається цей же метод базового класу форми.

Після методу Dispose () починається найцікавіше, а саме, виклик методу InitializeComponent (). Ви не бачите цього методу? Але ви бачите наступний рядок, написану сірим кольором:

Windows Form Designer generated code

Якщо так, то клацніть зліва від цього рядка на хрестику, який знаходиться на полях. Це змусить редактор коду розкрити регіон. Що таке регіон? Це блок коду, оточений ключовими словами #region ххххх і #endregion, де хххх - це ім'я регіону. Написавши це в коді, зліва від рядка з #region на полях ви побачите хрестик, за допомогою якого можна згортати весь код, виділений цими двома ключовими словами. Звернувши блок коду, ви будете бачити тільки ім'я регіону.

Повернемося до методу InitializeComponent (). Згадайте розд. 2.2, де ми розглядали конструктор нашої форми. Там ми говорили про те, що в конструкторі викликається метод з точно таким же ім'ям. Так ось він де знаходиться. І хоча він реалізований в іншому файлі, він все ж залишається частиною того ж partial класу.

Незважаючи на те, ЩО назву методу InitializeComponent () перекладається як "ініціалізувати компонент", метод ініціалізує властивості форми, а також створює всі елементи управління, які ми поставимо на форму візуально. Так, саме візуально і тільки візуально. Ручками в цей метод нічого писати не рекомендується, інакше дизайнер може виявитися нездатним зрозуміти ваші благі наміри і ваш мега-код при спробі відкрити форму в дизайнері він поверне помилку. Якщо й виникне необхідність вносити якісь зміни в метод InitializeComponent (), то робіть це дуже акуратно і обережно.

Тепер одним оком подивимося, що відбувається всередині цього методу. На самому початку викликається метод SuspendLayout () для нашої форми (про те, що викликається метод саме поточної форми, говорить слово this). Цей метод змушує систему призупинити реагування на зміну атрибутів. Справа в тому, що при зміні будь-якого атрибуту система буде перемальовувати форму. При ініціалізації найчастіше доводиться змінювати відразу кілька атрибутів, і після зміни кожного з них реагувати і змінювати форму невигідно. Набагато ефективніше змінити всі атрибути, а потім вже хай форма один раз відреагує на всі зміни і перемалюється відповідно до змін в потрібному місці.

Отже, після виклику методу SuspendLayout () для нашого вікна воно не буде реагувати і змінювати свою форму при зміні атрибутів, а зробить це після виклику методу ResumeLayout ().

Далі йде зміна властивостей форми. Ми поки не будемо розглядати ці властивості, все прийде з часом. Хочу тільки сказати, що середовище розробки і генератор цього коду мудрі, як ніколи, і допомагають нам, як тільки можливо. У методі InitializeComponent () з'явиться код для ініціалізації всіх кнопок, які ви будете мати у своєму розпорядженні на формі, і всіх інших елементів управління, Щоб простіше було працювати з методом, генератор буде групувати код так, щоб код ініціалізації одного елемента управління перебував у одному місці, а не розкиданий по всьому методу InitializeComponent ().

До того ж, перед початком ініціалізації чергового елемента буде йти коментар, в якому буде вказано ім'я елемента управління, властивості якого будуть далі змінюватися. У нашому прикладі немає нічого крім форми, але, незважаючи на це, перед початком зміни її властивостей стоїть коментар. Спасибі розробникам Visual Studio зате, що не забувають про нас.

2.4.  Hello Visual World

Тепер можете запустити програму за допомогою клавіші <F5>, як ми це робили у випадку з консольними додатками. На екрані має з'явитися вікно таких же розмірів, які були в вікні дизайнера.

Описание: C:\!!C#\media\image5.png

Мал. 5. Панель Properties з властивостями форми

Щоб наш приклад став повноцінним додатком "Hello World", з візуальним вікном, давайте змінимо заголовок вікна. Для цього потрібно переключитися на візуальну форму, що можна зробити декількома способами, наприклад просто клацнути двічі по імені файлу Forml.cs в панелі Solution Explorer. За замовчуванням форми з візуальним інтерфейсом відкриваються саме в візуальному дизайнері. Якщо у вашому середовищі розробки сталося не так, то можна натиснути правою кнопкою миші по імені файлу і із контекстного меню вибрати View Designer (Показати дизайнер). Якщо ви перебуваєте у вікні коду, можна натиснути комбінацію клавіш <Shift> + <F7>.

У дизайнері повинна бути обрана форма, тоді в панелі Properties з'являться властивості форми (рис. 5). В принципі, у нас нічого крім форми немає, тому, все одно будуть відображатися властивості саме форми, але головне, щоб панель Properties була присутня на екрані. Якщо ви її не бачите, виберіть в головному меню View | Properties Window.

В панелі Properties в лівому стовпчику знайдіть властивість Text і навпроти нього змініть в правій колонці назву заголовка на "Hello world" (за замовчуванням воно дорівнює імені класу). Ось тепер можна запускати додаток знову і спостерігати в заголовку вікна велику фразу, з якої починали вчитися програмуванню багато знаменитих програмістів.

Ми зробили невелику зміну, але вона дуже важлива для нас, тому що ми дізналися, як працювати з властивостями в візуальному дизайнері, і навчилися змінювати їх значення. Тепер можете повернутися в файл Form1.Designer.es і подивитися на метод ініціалізації компонентів. Зверніть увагу на наступний рядок коду:

this.Text = "Hello World";

У відповідь на зміну в візуальному дизайні середовище розробки згенерувало відповідний код. Ми могли б ручками написати цей же код, адже тут просто властивості Text поточного об'єкта присвоюється рядок, але через візуальний дизайнер було цікавіше і простіше.

3.    Властивості форми

Ми вже побачили, що властивості можуть змінюватися як візуально, так і програмно. Візуальні зміни дизайнер оформляє в коді методу InitializeComponent (). Якщо ви вирішили самі робити зміни властивостей в коді, то це можна зробити в конструкторі і обов'язково після виклику методу InitializeComponent (). Якщо написати код змін до виклику цього методу, то вони можуть виявитися марними, якщо дизайнер згенерує свій код в методі ініціалізації компонентів.

Відкрийте зараз код форми (Form.css) і спробуйте в коді конструктора привласнити властивості Text поточної форми якесь значення, наприклад, як показано в наступному прикладі:

public Form1()

{

InitializeComponent() ;

Text = "Це змінено в коді";

}

Відкрийте програму і переконайтеся, що в заголовку вікна відображається нове повідомлення. Давайте повернемося в візуальний дизайнер і подивимося, що ще у нас є в панелі Properties. Там дуже багато властивостей, і всі вони успадковуються нашою формою від класу Form. Ми можемо наділити форму додатковими властивостями, але у нас і так достатньо успадкованого, з чим потрібно ще розібратися. Ми будемо розглядати в міру потреби ті властивості, які будуть нам потрібні. Зараз же обмежимося тільки найосновнішими і найнеобхіднішими:

+ Background Color - колір фону вікна. Дана властивість має тип класу Color. Якщо клацнути в полі навпроти властивості, то з'явиться кнопка списку. Клацніть по ній, і ви побачите панель вибору кольору, як на рис. 6.

Описание: C:\!!C#\media\image6.jpeg

Мал. 6. Панель вибору кольору

Панель складається з трьох закладок: Custom (Довільні), Web (Web-кольори) і System (Системні). Для вікон бажано вказувати один із системних кольорів і краще, якщо це буде control для діалогових вікон і Window для вікон, які повинні відображати дані;

+ Cursor - дозволяє задати курсор, який буде відображатися в момент, коли курсор миші знаходиться над поверхнею вікна. При зміні цієї властивості в візуальному дизайнері з'являється випадаючий список, в якому перераховані назви типів курсорів і навіть показані їх зображення;

+ Enabled - дозволяє задати доступність вікна. Якщо властивість рівна false, то компонент не реагуватиме на дії користувача, буде недоступний;

+ Font - шрифт, який буде використовуватися для виведення тексту поверх вікна. Для вікна це на перший погляд не дуже актуально. Але велика актуальність цієї властивості проявляється у компонентів, які містять написи. Щоб змінити шрифт, можна піти двома шляхами:

♦ виділити рядок з властивістю Font, і в правому кутку з'явиться кнопка з трьома крапками. Клацніть по ній, і ви побачите стандартне вікно завдання властивостей шрифту;

♦ властивість шрифту насправді є самостійним класом Font зі своїми властивостями. Ви можете редагувати їх кожну окремо. Для цього потрібно клацнути по кнопці з хрестиком зліва від імені властивості. У вікні Properties властивості форми розсунуться, поступившись місцем властивостями шрифту (рис. 7);

Описание: C:\!!C#\media\image7.jpeg

Мал. 7. Властивості для налаштування властивостей шрифту

+ ForeColor - колір переднього плану, який найчастіше використовується в якості кольору тексту. Якщо ви подивитеся на доступні властивості шрифту, то помітите, що серед них немає кольору. Колір тексту задається через ForeColor;

+ FormBorderstyle - стиль контуру форми. Ця властивість є переліком, і в редакторові властивостей з'являється випадаючий список для вибору із наступних елементів (рекомендую на реальному додатку спробувати встановити кожну із властивостей і подивитися результат особисто):

♦ None - контуру не буде;

♦ FixedSingle - тоненький фіксований контур, який не дозволяє змінювати розміри вікна;

♦ Fixed3D- контур фіксований, який дозволить змінювати розміри вікна, але тривимірний, що створює ефект утоплення вікна;

♦ FixedDialog - схожий на FixedSingle, тільки в заголовку вікна не буде іконки. Такий контур найчастіше використовують для діалогових вікон;

♦ Sizable - стандартний контур, що дозволяє змінювати розміри вікна;

♦ FlxedToolWindow- контур з дуже тоненьким заголовком вікна, що не дозволяє змінювати розміри вікна. Такі вікна найчастіше використовуються для вікон з кнопками, наприклад вікно інструментів в Abode Photoshop;

♦ SizableToolWindow- те ж саме, що І FixedToolWindow, тільки з можливістю змінювати розмір вікна;

+ Icon - в цій властивості можна задати іконку для форми. Тут теж є кнопка, яка викликає стандартне вікно для відкриття файлу. Завантажена іконка потрапить до resx-файлу форми;

+ Location - положення вікна відносно лівого верхнього кута екрану. Така ж властивість є і у компонентів, але там відстань відраховується від лівого верхнього кута компонента батька, на поверхні якого знаходиться наш елемент керування. Дана властивість складається з двох складових - х та у, які розкриваються, якщо клацнути по кнопці з хрестиком зліва від імені властивості;

+ MainMenuStrip- в цій властивості можна задати компонент меню, який буде використовуватися в якості головного меню для вікна. Для цього на формі повинен стояти компонент класу MenuStrip. Тоді цей компонент можна буде вибрати зі списку;

+ MaximizeBox- логічне значення, яке визначає, чи повинна відображатися в заголовку вікна кнопка максимізації вікна. Якщо у вас вибраний стиль вікна, що не дозволяє змінювати розміри вікна, то переконаєтеся, що ця властивість рівна false, щоб заховати кнопку. Незважаючи на те, що форма не дозволяє зміну розмірів, кнопка максимізації без проблем відкриє віконце на повний екран;

+ MaximumSize- дозволяє задати максимальні ширину та висоту вікна. Користувач не зможе розтягнути вікно більше, ніж зазначені розміри;

+ MinimizeBox- логічне значення, що визначає, чи потрібно відображати кнопку згортання вікна;

+ Minimum Size- мінімальні розміри вікна, менше яких вікно не може бути зменшено. Таке обмеження може стати в нагоді, якщо занадто маленькі розміри псують дизайн вікна;

+ Name - назва форми та ім'я змінної об'єкту, яку ви можете використовувати в коді для доступу до властивостей об'єкта та для виклику його методів;

+ Opacity- відсоток прозорості вікна. За замовчуванням властивість дорівнює 100%.  Вікно абсолютно непрозоро. Якщо потрібно наполовину просвітити задній план, то можна встановити значення в 50%;

+ Padding- відступи від країв вікна. Властивість складається з п'яти значень: Аll, Left, Toр, Right, Bottom, що відповідає відступами з усіх боків, зліва, зверху, праворуч та знизу. Якщо встановити відступ зліва в значення 10, то ліва кромка вікна буде розміром в 10 пікселів;

+ Show Icon - логічне значення, що визначає, чи потрібно показувати іконку в заголовку вікна;

+ ShowInTaskBar - чи потрібно відображати вікно в панелі завдань. Головне вікно найчастіше потрібно відображати в панелі завдань, а ось для дочірніх та діалогових вікон цю властивість краще відключати, інакше для однієї програми з різними віконами в панелі завдань буде створюватися кілька міток. Як правило, цього не повинно бути;

+ Size - розмір вікна, його ширина та висота;

+ StartPosition- початкова позиція вікна. У цієї властивості є випадаючий список для вибору одного із наступних значень:

♦ windowsDefaultLocation - положення вікна визначається ОС;

♦ windowsDefault Bounds - система визначатиме не тільки положення, але і розміри вікна;

♦ CenterParent - розташувати вікно по центру батьківського вікна. На мій погляд, це значення найкраще використовувати для всіх дочірніх вікон;

♦ Manual - розташування буде задаватися програмістом самостійно Через властивість Location;

♦ CenterScreen - відцентрувати по центру екрана;

+ Tag - дуже цікава властивість, але вона абсолютно ні на що не впливає. Проте навіщо тоді вона потрібна? Ви можете зберігати в цій властивості будь-яку додаткову інформацію, тому що це властивість має тип object;

+ Text - текстовий заголовок вікна

+ TopMost - логічне значення, яке визначає, чи має вікно розташовуватися поверх інших вікон. Відразу хочу попередити - не зловживайте цією властивістю в своїх програмах для головного вікна, а якщо і вирішите розташувати вікно поверх інших, то дайте користувачу можливість відключати цю особливість. Багатьох користувачів дратують вікна, які перекривають робочу область. А ось використання цієї властивості для дочірніх вікон програми може бути дуже зручним. Якщо вікно показано модально, ця властивість дозволить вікну бути поверх інших і не сховатися за іншими вікнами;

+ WindowState - стан вікна. Тут можна вказати одне з трьох значень:

Normal - нормальний стан;

Maximized - вікно повинно бути розгорнуто на весь екран;

Minimized - вікно повинно бути мінімізовано.

Нагадую, що наші лкції - не довідник по функціях, такий довідник вже є, і називається він MSDN. Ми розглядаємо тільки найцікавіше і вчимося програмувати.

Чому я розглянув ці властивості? Більшість з них є не тільки у форм, а й у будь-якого типу візуальних компонентів. Просто вони успадковуються від загальних для всіх компонентів предків. До того ж я вибрав різні типи, щоб ви побачили, що в вікні властивостей для редагування різних компонентів можуть викликатися різні редактори.

Тепер давайте подивимося, що приховують під собою кнопки з хрестами зліва від деяких властивостей. Хрестики можуть стояти у тих властивостей, які самі по собі є об'єктами певного класу. Наприклад, властивість Font є класом Font. Розкриваючи хрестик у властивості Font, ви побачите властивості класу Font. Наприклад, розкривши шрифт Font, ви можете побачити властивість size - розмір. Поний шлях до розміру шрифту буде виглядати так:

Control.Font.Size = 10;

У цьому прикладі розмір шрифту змінюється на 10. Для цього ми змінюємо властивість size об'єкта класу Font, який є властивістю нашого елементу управління. Може існувати і довша вкладеність, але в C # я не пригадую вкладеності більше 5, та й більше 3-х зустрічається вкрай рідко. Коли ви самі будете проектувати ваші програми і класи, не робіть вкладеності більше 4, інакше це можуть бути просто не дуже добре спроектовані класи, а робота з ними буде незручна і навіть жахлива.

Відразу ж слід розглянути структури даних, з якими ви будете зустрічатися при роботі з компонентами і формами: Size і Location. Розглянемо кожну окремо.

Структура size призначається для завдання розмірів, наприклад розмірів компонента або форми. У структури є два поля - width і Height - для вказівки ширини і висоти відповідно. Ви не можете змінювати властивості структури, і наступний рядок призведе до помилки компіляції:

Size.Height = 100;

Завжди потрібно створювати новий екземпляр структури. Наприклад, наступний приклад встановлює розміри вікна в 200x300:

Size = new Size(200, 300);

Тип даних Size використовується також ДЛЯ ВЛАСТИВОСТЕЙ Maximum Size, Minimum Size, AutoScrollMargin І AutoScrollMinSize.

Структура Location має тип Point. І судячи з назви, з її допомогою найчастіше задають точку. Наприклад, цей тип використовується для завдання положення когось компонента або форми. Ця структура містить два важливих властивості - х і у, які зберігають зміщення по відповідним координатним осям. Наступний рядок переміщує поточну форму в позицію 10x10;

this.Location - new Point(10, 10);

У обох структур властивості, які визначають розмір і положення, мають тип даних цілого числа int. Ви не можете задати дробове число в якості положення, та це й не має сенсу в WinForms, адже розміри форми і положення визначаються пікселями, а це мінімальна одиниця в даному випадку, і вона не може ділитися.

4.    Методи форми

Клас Form містить безліч методів, які ми можемо використовувати і які успадковуються нашими формами:

+ Show() -Відобразити створене вікно немодальним. Немодальне вікно не блокує виконання батьківського вікна (в якому воно було створено). Це означає, що обидва вікна будуть працювати як би паралельно. Ви можете перемикатися між ними і працювати в двох вікнах одночасно;

+ ShowDialog () - відобразити вікно модально. У цей момент у вікні, в якому ви викликали метод, виконання блокується до тих пір, поки ви не закриєте дочірнє вікно, яке відобразили за допомогою ShowDiaiog (). Ви можете працювати тільки з дочірнім вікном, і воно завжди відображається поверх свого батьківського вікна. Таким чином відображаються всі діалогові вікна, наприклад вікно відкриття документа, вікно властивостей і т.д.;

+ Hide () - заховати вікно, не знищуючи його. Ця дія має сенс для немодальних вікон, які не блокують батьківське вікно; close () - закрити форму. При закритті форми її об'єкт знищується;

+ Invalidate () - Перемалювати форму.

Методи ми також будемо розглядати в міру потреби, а поки цього достатньо.

5.    Події на прикладі форми

У платформі .NET, як і в Win32, для інформування про виникнення якогось стану або про дію використовуються події, або іноді їх ще називають повідомлення (по-англійськи events). Наприклад, у відповідь на зміну положення вікна воно генерує подію певного класу, яку ми можемо перехопити.

Для того щоб перехопити подію, потрібно створити її обробник. Обробник події по суті є методом, який реєструється на відловлювання певної події від певного елемента управління / форми / компонента. Коли настане подія, то цей самий елемент управління / форма / компонент викличе метод, в якому ми можемо написати код реакції на подію.

За допомогою візуального дизайнера Visual Studio створення обробників подій перетворюється в тривіальну задачу. На рис. 8 показана панель Properties в режимі перегляду подій. Щоб побачити щось подібне, потрібно виділити компонент, подію якого ви хочете зловити, і натиснути кнопку Events в панелі Properties (на рис. 8 ця кнопка виділена колом). Щоб повернутися назад до перегляду властивостей, потрібно клацнути по кнопці Properties, яка знаходиться лівіше.

Тепер, щоб створити потрібний обробник події, досить двічі клацнути в полі одразу після назви події. Середовище розробки створить необхідну подію, додасть її реєстрацію У своєму методі InitializeComponent (), переключиться в режим коду і встановить курсор в тіло методу, створеного для обробки події.

Давайте створимо обробник події Mouse Click. Виділіть форму, перейдіть в панель Properties в режим перегляду подій Events і двічі клацніть напроти події.

Буде створено метод Form1_MouseClick ():

MessageBox.Show("Клац");

Описание: C:\!!C#\media\image8.jpeg

Мал. 8. Панель Properties під час перегляду подій

private void Form1_MouseClick(object sender, МоuseEventArgs e)

{

}

Я тут додав всередину методу обробки події виклик статичного методу show () класу MessageBox. Цей метод відображає на робочому столі діалогове вікно з повідомленням, яке ви передали в якості параметра. У нашому випадку кожен раз, коли ви будете клікати по формі, буде з'являтися повідомлення "Клік".

Дуже цікавим є питання про те, які події отримали форма, коли з'являється і знищується. При завантаженні форми генеруються наступні події і саме в такій послідовності:

+ Load - завантаження;

+ Activate - активація;

+ VisibleChanged - змінилася властивість Visible.

А під час закриття форми генеруються наступні події:

+ Deactivated - деактивовано;

+ Closing - закриття форми (можна скасувати закриття);

+ Close - форма закрита, і назад дороги немає.

Подія Load генерується, коли ви вперше викликається метод Show () для відображення форми. Подивимося на наступний приклад:

MyForm form = new Form ();

form.Show (); // Відобразити форму

form.Hide (); // Заховати за допомогою Hide ()

form.Show (); // Показати знову

Подія Load буде згенеровано тільки під час першого виклику методу Show (), тому що в цей момент буде відбуватися завантаження форми. Коли ми викликаємо метод Hide (), то форма залишається завантаженою, просто ховається з екрану. Наступний виклик методу show () тільки змінює видимість вікна, а завантаження не буде, тому і подію Load більше генеруватися не буде.

Дуже часто у вас будуть виникати казуси з випадковим створенням подій. Наприклад, якщо двічі клацнути по компоненті в візуальному дизайнері, то буде створений обробник події за замовчуванням для цього компонента. Для кнопки подією за замовчуванням є click, і якщо ви випадково двічі клацнете по компоненті в візуальному дизайнері, то буде створений цей обробник події. А якщо ви не хотіли його створювати? Залишати заготовку методу в коді? Напевно краще все ж прибрати обробник події, щоб він не заважав. Як це зробити? Існує кілька варіантів:

1.     Виділіть компонент в візуальному дизайнері і перейдіть в режим Events в панелі властивостей. Напроти події видаліть в полі назву методу, створеного для обробника події. Візуальний редактор видалить реєстрацію події, яку він автоматично додав до свого метод InitializeComponent (). Якщо в обробнику події не було коду, то заготовка для методу зникне і з коду.

2.     Якщо обробник події містить код, але він вже не потрібен, то можна спочатку видалити код з обробника події, а потім виконати дії з пункту 1.

3.     Якщо обробник події містить код, то можна спочатку видалити ім'я обробника події в режимі Events панелі властивостей, а потім безболісно видалити код методу.

4.     Якщо ви створили обробник події і тут же видалили метод в редакторі коду, то при цьому середовище розробки не видалить реєстрацію події в методі InitializeComponent (). Це доведеться робити вручну. Як це зробити безболісно? Давайте подивимося на прикладі.

private void button1_Сlick(object sender, EventArgs e)

{

}

Видаліть цю заготовку кода з редактора і спробуйте скомпілювати проект. Внизу вікна з'явиться повідомлення про помилку, як на рис. 9. У цій помилці компілятор повідомляє нам, що обробник події не знайдено. Двічі клацніть по помилці, і відкриється закладка з файлом (Forml.Designer.es), де знайдена помилка, і буде виділено рядок кода, яку додав візуальний редактор для реєстрації події, для того, щоб позбутися від помилки, потрібно видалити рядок, яку виділив нам редактор. Таким чином, ви вручну видалите реєстрацію, і проект відкомпілюйте без проблем.

Описание: image9

 

 

 

 

 

 

 

6. Компоненти .NET

Компоненти в Visual Studio діляться на два типи - візуальні іневізуальні. Візуальні компоненти (мітки, кнопки, поля введення і т.д.) з'являються на формі. Невізуальні компоненти (такі, як таймер) з'являються на спеціальній панелі і видимі тільки під час дизайну форми у вигляді імен з іконками. Під час ви-конання програми невізуальні компоненти не відображаються.

Доступ до компонентів .NET можна отримати з панелі Toolbox (рис. 10). Якщо її не видно, то потрібно вибрати в меню View | Toolbox.

Описание: image10



Мал. 10. Панель Toolbox з компонентами

Для вашої зручності всі елементи управління згруповані по розділах. Ви можете створювати свої розділи і поміщати в них будь-які компоненти, але для початку краще залишити все за замовчуванням. Вони досить зручно продумані. У розділі All Windows Forms (Всі Windows-форми) знаходяться всі компоненти. Якщо ви забули, в якому розділі шукати потрібний елемент управління, можете розкрити цей розділ і знайти потрібний елемент в ньому. Всередині розділів всі компоненти відсортовані по імені.

Компоненти на формі можна перетягувати мишею, візуально встановлюючи їх положення. Коли ви виділяєте компонент, зверніть увагу на точки, які з'являються навколо контуру виділення. У ті сторони, на яких є жирні точки, можна розтягувати компонент. Наприклад, виділіть форму і у неї на рамці виділення будуть точки тільки справа і знизу. Це означає, що ви можете змінювати висоту і ширину форми переміщенням правого і нижнього країв форми.

Спробуйте встановити на форму кнопку Button з розділу Common Controls (Загальні елементи управління). Виділіть її та переконайтеся, що навколо кнопки з'являються жирні точки у всіх напрямках, а значить, з кнопкою можна робити все, що завгодно.

Спробуйте тепер перетягнути на форму компонент-мітку Label. Виділіть її. Тут є чому здивуватися, тому що у цього компонента немає квадратів по контуру. Є тільки маленький квадрат в лівому верхньому кутку компонента. Це означає, що у компонента не можна змінювати розміри, але можна змінювати його положення. Насправді змінювати розміри можна, просто за замовчуванням компонент створюється в режимі Авторозмір.

Всі візуальні елементи управління містять серед предків клас control. Цей клас наділяє компоненти усіма необхідними властивостями і методами, щоб бути цими компонентами. Давайте стисло нагадаємо основні властивостями, щоб не повторюватися в майбутньому, тим більше що багато з них ми вже бачили у форми:

+ Anchor - властивість дозволяє визначити, до якої сторони батьківського компонента прикріплювати компонент;

+ BackColor - колір фону;

+ Cursor - курсор;

+ Dock - вирівнювання;

+ Font - шрифт;

+ ForeColor - колір переднього плану;

+ Height - висота елемента управління;

+ Left - ліва позиція компонента відносно батька;

+ Location - положення;

+ MaximumSize - максимальний розмір елемента керування;

+ MinimumSize - мінімальний розмір елемента керування;

+ Name - назва об'єкта, тобто ім'я змінної для об'єкта елемента управління;

+ Padding - відступи з усіх сторін батьківського компонента / форми;

+ Size - розмір компонента - ширина і висота;

+ Tор - позиція компонента по вертикалі відносно батька;

+ Visible - якщо дорівнює true, то компонент видно, інакше ні;

+ Width - ширина компонента.

Декілька зауважень з приводу властивості Anchor. За замовчуванням компоненти прикріплюються до лівої і верхньої сторони батька. Якщо прикріпити до лівої і правої, то при зміні розміру форми змінюватимуться і розміри компонента. Прикріплення ніби вказує, що відстань від компонента до краю форми не повинно змінюватися, а значить, при зміні форми доводиться змінювати розміри компонента. Якщо прикріпити тільки до правого боку, то при зміні розміру форми компонент буде рухатися разом з правої кромкою вікна як хвостик, тому що в цьому випадку відстань від правого краю до компонента не повинна змінюватися.

Як змінювати прикріплення? Виділіть властивість Anchor і натисніть на кнопку виклику списку в редакторові властивостей. З'явиться невелике вікно (рис. 11), в якому від центру в різні боки йдуть смужки. Темні смужки говорять про те, що в цей бік зроблено прикріплення, а білі говорять про те, що прикріплення немає. Клацайте по смужках, щоб встановлювати або прибирати прикріплення.

Описание: image11

Рис. 11. Вікно встановлення якорів

Ще одна властивість, на якому слід зупинитися, - Dock. Якщо натиснути по випадаючому списку в редакторі властивостей для Dock, то з'явиться маленьке вікно, яке являє собою невеликий компонент. Він розбитий на сектори, як показано на рис. 12, тільки підписів російською у вас не буде. Ці підписи я додав в малюнок для зручності.

Описание: image12

Клацаючи по секторам, ви вирівнюєте свій компонент на поверхні компонента контейнера, на якому він стоїть. Наприклад, якщо ваш компонент стоїть на поверхні форми, і ви клацнете по самому верхньому сектору для вирівнювання поверху, то ваш компонент розтягнеться уздовж верхнього краю вікна, як це роблять меню і панелі в більшості додатків. Таким чином, дуже просто і зручно створювати потужні й гнучкі інтерфейси.

7.   Загальні компоненти

Давайте пробіжимося по компонентах і подивимося їх основні властивості і методи використання, щоб згодом було простіше працювати з ними. Я розбив розгляд компонентів на три великі розділи, відповідно до їх положення на панелі Toolbox. У цьому розділі мова піде про компонентах з групи Common Controls.

Ми будемо розглядати компоненти в тому порядку, в якому вони знаходяться в групі, тобто за алфавітом. Деякі можуть бути пропущені.

Ми будемо розглядати властивості в основному з точки зору дизайну, але не забувайте, що це просто властивості компонентів, а значить, ви можете змінювати їх в коді програми. Згодом ми будемо частіше звертатися до властивостей і методів компонентів саме в коді.

7.1         Button

Створіть новий проект і перетягніть на його форму кнопку Button. Розмістіть її ближче до лівого верхнього кута вікна. Виділіть кнопку і знайдіть властивість Text. Ця властивість відповідає за текст, який буде відображатися на поверхні кнопки. За замовчуванням властивість дорівнює імені компонента, а ім'я компонента іменується як buttonN, де N- це номер компонента з таким ім'ям, тобто сама перша кнопка на формі отримає ім'я button1.

Давайте спробуємо зробити щось діюче в нашому прикладі. Просто поставити кнопку буде замало. Двічі клацніть по ній, щоб створити обробник події click, який буде викликатися кожен раз, коли ви натискаєте мишею по кнопці. Це, напевно, найпопулярніша властивість цього компонента, і саме цей обробник створюють програмісти в більшості випадків.

Будь-яку властивість можна змінювати і під час виконання програми. Давайте після натискання кнопки будемо збільшувати значення позиції кнопки, тобто збільшувати ліву і верхню позиції (властивості Left і тор відповідно). Отже, в методі для обробника події пишемо:

private void buttonl_Click(object sender, EventArgs e)

{

myFirstButton.Left += 5; myFirstButton.Top += 5;

}

Для чого найчастіше використовується кнопка? Звичайно ж, щоб на неї натискали користувачі, тому в реальних додатках, як правило, доводиться змінювати властивість імені, властивість тексту і виловлювати подію Click. Ще одна властивість, яка може вас зацікавити, - image, через яку ви можете задати кнопці якусь картинку.

Давайте зупинимося і подивимося, як встановлюється картинка. Виділіть властивість image кнопки в панелі Properties. Клацніть по з'являючомуся в рядку властивості кнопки, і ви повинні побачити вікно завантаження зображення Select Resource (рис. 13).

Описание: image13

Рис. 5.13. Вікно завантаження зображення



У цьому вікні зліва можна побачити два перемикача:

+ Local resource - зберегти картинку як локальний ресурс. Зображення буде збережено в файлі ресурсів форми і буде доступно тільки для кнопки. Якщо ви захочете використовувати таке ж зображення на інший кнопці або в меню, то доведеться завантажувати зображення ще раз, а це значить, що ресурси будуть дублюватися, і розмір програми невиправдано збільшиться;

+ Project resource file - ресурс буде збережений у файлі ресурсів проекту, який знаходиться в папці Properties. Можна змінити файл ресурсів, пропонований за замовчуванням, якщо їх декілька. Потрібно тільки вибрати ім'я файлу в випадаючому списку. Збереження картинки в файлі ресурсів проекту означає, що в будь-якому іншому елементі управління в цьому ж проекті не потрібно завантажувати зображення знову, досить буде вибрати його ім'я в списку під перемикачем Project resource file. На рис. 13 в моєму файлі ресурсів вже є картинка з ім'ям help, яку я вже завантажував, і тепер її можна просто вибрати і призначити іншим елементам.

Щоб завантажити картинку і додати її в обраний файл ресурсів (локальний або обраний), натисніть кнопку Import. Щоб призначити вибране / завантажене зображення, натисніть кнопку ОК.

Тепер дуже важливим моментом є положення картинки на кнопці. За замовчуванням вона опиниться під текстом. Положення картинки визначає властивість TextImageRelation (відношення тексту і картинки). Тут можна вибрати одне з наступних значень:

+ Overlay - текст буде поверх картинки;

+ Image Above Text - тєкст буде під картинкою;

+ TextAboveImage - текст буде над картинкою;

+ ImageBeforeText - картинка буде зліва від тексту;

+ TextBeforeImage - текст буде зліва від картинки.

Ще одна властивість, на якій Я хочу зупинитися, - Text Align. Якщо виділити його у вікні властивостей, то з'являється кнопка виклику списку, але якщо клацнути по ній, то з'явиться спливаюче вікно, як на рис. 14. Тут 9 кнопок у вигляді прямокутників. Клацаючи по кнопках, ви можете вибрати, з якого краю кнопки буде вирівнюватися текст. За замовчуванням обрана сама центральна кнопка, тобто текст буде вирівняний по центру. Якщо вибрати праву нижню кнопку, то текст буде вирівняний до правого нижнього кута кнопки.

Описание: image14

Рис. 14. Вікно вибору вирівнювання тексту відносно кнопки



 

7.2         CheckBox

 

Компонент CheckBox дозволяє вибрати одне з двох станів, не рахуючи невизначеного стану, який не можна встановити програмно. Цей компонент використовується, коли потрібно, щоб користувач вибрав один з двох варіантів - так чи ні. Наприклад, у вікнах налаштування шрифтів прапорцем CheckBox вибирають, повинен бути шрифт напівжирним чи ні, чи повинен він бути підкресленим чи ні, і завжди питання буде: так чи ні.

У компонента всього дві цікавих властивості, окрім загальних для всіх компонентів властивостей:

+ Checked- властивість рівно істині (true), якщо користувач поставив прапорець, інакше буде брехня (false);

+ Check State- стан у вигляді перерахування, в якому можна вказати одне з трьох значень:

♦ Indeterminate-невизначено;

♦ unchecked - ідентично значенням властивості checked, рівному false;

♦ checked - ідентично значенням властивості checked, рівному true.

Наступний приклад показує, як можна програмно змінювати значення цих властивостей:

runAtStartupCheckBox.CheckState = CheckState.Indeterminate; deleteOnExitCheckBox.Checked = false;

 

У першому рядку стан компонента скидається на невизначений, а у другому рядку Іншому компоненту ВЛАСТИВІСТЬ Checked міняється на false.

У цього компонента є три цікаві події, які відносяться саме до нього і можуть стати в нагоді вам:

+ CheckedChanged - подія генерується кожен раз, коли змінюється властивість Checked;

+ Checked StateChanged - подія генерується При зміні значення властивості CheckedState;

+ Click - властивість генерується при натисканні на компоненту.

7.3         CheckedListBox

Припустимо, що вам потрібно створити список, в якому поруч із елементами користувач повинен буде ставити відмітки. Якщо список маленький і не дуже однорідний, то можна обійтися кількома елементами управління типу CheckBox. А якщо список складається з 20 елементів? А якщо список динамічний і може змінюватися? Ось тут на допомогу приходить CheckListBox. Приклад такого компонента показаний на рис. 15.

Описание: image15

Рис. 15. Приклад компонента CheckedListBox



 

На рис. 15 показано вікно, в якому у вигляді списку з прапорцями CheckBox знаходиться список покупок. Мається на увазі, що користувач йде з ноутбуком або іншим пристроєм по гіпермаркету і відзначає за своїм списком, що він купив, а що ні. Так як список щотижня відрізняється, то реалізовувати цю динаміку набагато простіше через компонент CheckedListBox.

Створіть новий додаток і помістіть на його форму екземпляр компонента CheckedListBox. Виділіть компонент і в панелі Properties знайдіть властивість Items. Виділіть його, а потім клацніть по з'явившійся кнопці. З'явиться вікно невеликого текстового редактора, в якому можна вводити елементи списку. Кожен окремий елемент потрібно писати в новому рядку.

За замовчуванням всі елементи списку розташовані в одну колонку. Якщо ви хочете розташувати їх в кілька колонок, як це зроблено у мене, то потрібно встановити властивість Multicolumn в true. Щоб об'єкти у списках були відсортовані, властивість Sorted потрібно встановити в true.

Як працювати з компонентом? Нам може знадобиться дізнатися, який елемент вибраний зараз, тобто на якому елементі зараз стоїть курсор. Це можна дізнатися через властивість SelectedItem наступним чином:

if (checkedListBox1.SeiectedItem != null)

checkedListBoxl.Selectedltem.ToString();

У першому рядку я перевіряю, чи не є виділений елемент нульовим. Якщо він нульовий, то нічого не виділено, і ми не можемо працювати з властивістю SeiectedItem, яка має тип Object, саме по собі є об'єктом класу. В такому випадку властивість нульова і для нього пам'ять не розподілена, а значить, звернення до властивостей або методів SeiectedItem призведе до помилки.

Якщо властивість не нульова, то ми можемо привести його до рядка і побачити ім'я елемента, який виділений. Саме це і відбувається в другому рядку.

Тепер подивимося, як можна дізнатися все елементи, на яких стоять мітки, тобто всі відмічені елементи. Виділені і відмічені елементи - це різні речі.

Відмічені елементи зберігаються у вигляді колекції (списку) у властивості CheckedIterns. Ми можемо перебрати цю властивість за допомогою циклу, наприклад, foreach:

foreach (String str in checkedListBox1.Checkedltems)

MessageBox.Show(str);

В даному випадку в циклі просто виводяться всі відмічені елементи у вікні повідомлень, тому якщо будете тестувати приклад, то не відзначайте занадто багато елементів, щоб багато раз не натискати кнопку ОК для закриття вікна повідомлень.

Ви можете управляти списком елементів У списку CheckedListBox. Список елементів зберігається у властивості items. Ця властивість має тип класу колекції Collection.

Наступний приклад показує, як можна додати новий елемент до списку:

checkedListBox1.Items.Add ("Це щось", true);

В якості першого параметра методу Add () колекції items передається рядок, що містить текст, який буде призначений в якості заголовка новому елементу. Другий параметр визначає, чи повинен новий пункт бути поміченим чи ні. Найчастіше колекції компонентів прийматимуть тільки один параметр - текстову назву. Але тут не зовсім звичайний компонент, тому що у елементів є властивість у вигляді прапорця, який можна встановити при створенні.

Наступний приклад показує один з варіантів видалення позначених елементів:

foreach (int index in CheckedListBox1.Checkedlndices) checkedListBox1.Iterns.RemoveAt(index);

В даному випадку запускається цикл, який перебирає всі елементи масиву, який знаходиться у властивості CheckedIndices. У цій властивості знаходиться масив чисел, які є індексами помічених елементів. Якщо нічого не позначено, то ця властивість містить порожній масив.

Всередині циклу викликається метод RemoveAt () властивості Items. Цей метод видаляє з колекції items елемент під індексом, зазначеним в якості параметра.

Таке видалення приховує в собі небезпеку. Спробуйте запустити приклад і виділити останні два елементи і натисніть кнопку видалення. Програма завершітработу аварійно. Припустимо, що в списку 10 елементів і ви виділили 9і 10для видалення. Після видалення 9-го кількість елементів скорочується до 9 і на наступному кроці видалення 10 стане неможливим, тому що він уже змістився на 9-ту позицію.

Проблему можна вирішити банальним запуском видалення починаючи з максимального індексу, до мінімального:

for (int i = listBox1.Checkedlndices.Count - 1; i >= 0; i--)

listBox1.Items.RemoveAt(listBox1.Checkedlndices[i]);

У цьому прикладі я запускаю цикл, починаючи з останнього елемента зі списку CheckedIndices, до нульового. властивість Count повертає кількість елементів в колекції. Не забуваємо, що індекси нумеруються з нуля, а кількість елементів відображає реальну кількість, тому при ініціалізації змінної i я віднімаю одиницю з кількості. Цикл йде з найбільшого до мінімального, тому на цей раз, якщо виділити останні два елементи з 10, спочатку буде видалений 10-й, а потім 9-й, що зовсім не порушує межі колекції. Після видалення 10-го в колекції залишається 9 елементів, а нам якраз потрібно видалити 9-й.

Серед подій компонента вас можуть зацікавити наступні:

+ SelectedIndexChanged- спрацьовує при зміні індексу виділеного елемента (властивість SelectedIndex);

+ SelectedValueChanged- спрацьовує при зміні виділеного елемента (властивість SelectedValue).

Наступний приклад показує обробник події SelectedValueChanged. При зміні виділеного елемента його заголовок буде відображатися на поверхні мітки selectedLabel:

private void checkedListBoxl_SelectedValueChanged( object sender, EventArgs e)

{

selectedLabe1.Text = checkedListBoxl.Selectedltem.ToString();

}

7.4. ComboBox

Випадаючий список СоmbоBох зручний тоді, коли потрібно вибрати одне значення з цілого списку. Створіть новий додаток і помістіть на форму екземпляр компонента ComboBox.

Елементи списку задаються у властивості Items, який має тип колекції, схожий з тим, що ми розглядали в розд. 7.3 у компонента checkedListBox.

Давайте подивимося, які найбільш цікаві властивості додає клас ComboBox до базового класу компонентів:

+ MaxDropDownItems - кількість видимих елементів в випадаючому списку, коли ви розкриєте його. За замовчуванням список розкривається на 8 видимих елементів, а для перегляду більшої кількості буде з'являтися смуга прокрутки. Якщо у вас всього 9 елементів, то іноді вигідніше розширити кількість видимих елементів, щоб не було смуги прокрутки;

+ DropDownStyle- стиль списку. Стилі в дії ви можете побачити на рис. 5.16, а значення у властивості можуть бути наступними:

♦ Simple- простий стиль, при якому поле вводу елемента і список для вибору видно одночасно;

♦ DropDown - ви можете відображати випадаючий список, клацаючи по кнопці зі стрілкою вниз, а також вводити будь-яке значення в поле вводу випадаючого списку з клавіатури;

♦ DropDownList - відрізняється від попереднього тим, що не можна вводити значення з клавіатури, тільки вибирати зі списку.

Описание: image16

Рис. 5.16. Стилі випадаючого списку ComboBox



Продовжимо знайомитися з методами колекції і подивимося, як можна додати відразу багато елементів. Для цього у колекції є метод AddRange (). Цьому методу передається масив об'єктів класу Object, а так як це предок для будь-якого класу, то це означає, що можна передати масив будь-яких значень. Щоб відобразити в списку елементи у вигляді рядків, компонент перетворює значення об'єктів в рядок за допомогою методу ToString (), що успадковується від Object.

Наступний приклад показує, як можна створити масив з елементів і тут же передати його методу AddRange () без збереження в будь-якій змінній:

comboBoxl.Items.AddRange{new String[] { "Відмінно", "Добре"});

Якщо необхідно очистити відразу всі елементи списку, то можна скористатися методом Clear () колекції: comboBox1.Items.Clear ();

Тепер подивимося, як можна дізнатися, який елемент представлений в випадаючому списку. Щоб дізнатися виділений елемент у вигляді тексту, можна використовувати властивість SelectedItem:

if (comboBox1.Selectedltem != null)

{

String str = comboBox1.SelectedItem.ToString();

MessageBox.Show(str);

}

else

MessageBox.Show("Нічого не виділено")

Перш ніж працювати з властивістю SelectedItem, бажано перевірити його на нульове значення. Якщо в випадаючому списку нічого не виділено, то SeLectedItem буде дорівнювати null. При спробі привести властивість до рядка за допомогою методу ToString (), коли властивість дорівнює нулю, програма згенерує помилку.

Якщо ви хочете дізнатися індекс виділеного елемента зі списку, то можна скористатися властивістю SelectedIndex. Ця властивість-число, і його перевіряти на null не потрібно. Якщо нічого не виділено, то властивість поверне -1. Це ж значення буде, якщо ви введете в поле своє значення, а не виберете щось зі списку.

Серед подій компонента вас можуть зацікавити SelectedIndexChanged і SelectedValueChanged, які ми вже бачили в розд. 7.3.

 

7.5 DateTimePicker

Цей компонент зручний в тих випадках, коли користувачеві потрібно вводити в програму дату або час.

Він виглядає як випадаючий список, тільки в правому куті замість стрілки, щоб відкрити список знаходиться іконка, після натискання якої з'являється спливаюче вікно для вибору дати. Ця дуже зручне вікно, яке дозволяє уникнути помилок при введенні дати.

У компонента багато цікавих властивостей, які дозволяють налаштувати зовнішній вигляд календаря на будь-який колір та смак. Але найбільш цікаві властивості - це функціональні:

+ Format - формат відображення значення. Тут можна вказати одне з наступних значень:

♦ Long - довгий формат, в якому місяць вказується назвою, а не числом;

♦ short - короткий формат дати;

♦ Time - відображати час для редагування;

♦ custom- настроюється формат. У цьому випадку формат відображення задається через властивість CustomFormat;

+ MaxDate та MinDate - значення максимальної та мінімальної дати, за межі яких не можна буде виходити;

+ ShowUpDown - показувати в компоненті справа дві кнопочки зі стрілками вгору та вниз, за допомогою яких можна збільшувати та зменшувати поточну частину часу.

Щоб отримати в коді обрану користувачем дату, можна використовувати наступний код:

DateTime dt = dateTimePicker1.Value;

У змінну класу DateTime зберігається вибране користувачем значення. Так, час в .NET представляється класом DateTime. Це не просто змінна, а клас з великою кількістю властивостей та методів.

Найцікавішою подією компонента можна назвати valueChanged, яке генерується кожен раз, коли ви змінюєте дату або час всередині компонента. Але користувач далеко не завжди може вибрати нове значення дати за один раз. Він може вибрати значення, подумати, а потім знову змінити його. Якщо ви хочете після змінити час або дату тут же перемальовувати щось, то це подія буде якраз до речі.

Якщо вам не потрібно відстежувати зміни, які робить користувач, а ви хочете отримати тільки остаточний вибір, то в цьому випадку може бути вигідніше обробляти подію Leave, яка генерується, коли компонент втрачає фокус вводу, тобто користувач переключився на роботу з іншим елементом управління.

7.6 Label та LinkLabel

Основна мета обох компонентів - створення підписів, а у LinkLabel є додаткові можливості для завдання частини тексту на компоненті у вигляді посилання, яке буде підкреслено, а при наведенні на неї курсор буде змінюватися на іконку з рукою.

У компоненти Label основними властивостями є:

+ Text - через цю властивість ми можемо задавати текст, який буде відображатися на поверхні компоненти, тобто текст компоненти;

+ AutoSize - за замовчуванням дорівнює true, щоб компонент автоматично брав мінімально необхідні розміри для відображення тексту. Якщо змінити текст, то компонента автоматично змінить свої розміри;

+ TextAlign- дозволяє вказати, по якій стороні компоненти повинен вирівнюватися текст. Ця властивість немає сенсу При AutoSize рівному true.

Компонент LinkLabel додає наступні властивості:

LinkColor І Visited Link Color - визначають колір посилання та колір посилання, якщо користувач вже клацав по ній;

+ Link Visited - властивість з булевим значенням, яка визначає, переходив користувач за посиланням. Ви повинні самі відслідковувати перехід;

+ LinkArea - область посилання всередині тексту. За замовчуванням весь текст є посиланням, але ви можете обмежити посилання, вказавши номер початкового символу у властивості start та кількість символів в посиланні у властивості Length, які з'являються, якщо розкрити властивість LinkArea у редакторі властивостей.

Незважаючи на те, що компонент LinkLabel схожий на інтернет-посилання, він тільки схожий, а не працює як інтернет-посилання. Якщо ви введете в текстове поле URL-адресу та перейдете по посиланню в запущеному додатку, нічого не відбудеться. Ви повинні самі написати код, який повинен виконуватися після натискання посилання, і робити це потрібно в обробнику події LinkClicked.

Хоча я відхожу зараз в сторону, я покажу вам, як можна в обробнику події запустити браузер і завантажити сторінку:

System.Diagnostics.Process.Start("http://www.google.com");

Як параметр цього методу передається рядок, який потрібно запустити в системі. В даному випадку це URL, а для обробки URL ОС Windows запустить браузер за замовчуванням і завантажить зазначену сторінку. Цією ж командою можна запустити файл на виконання. Для цього потрібно просто вказати ім'я файлу, який ви хочете відкрити або запустити.

7.7. ListBox

За своїми властивостями компонент дуже схожий на випадаючий список CheckedListBox, тому що вони дуже схожі за змістом. Але список ListBox не має біля кожного елемента списку компонента checkBox для того, щоб ставити прапорці.

З іншого боку, У ListBox працює властивість Selection Mode. Ви можете встановити його в MuitiSimple або MultiExtended, щоб дати можливість користувачу вибирати декілька елементів зі списку. У CheckedListBox спроба встановити будь-який з цих значень призведе до повідомлення про помилку.

Якщо потрібно дізнатися, який елемент зараз обраний, можна скористатися властивістю SeiectedItem. Якщо ви дозволили можливість множинного вибору, то список виділених елементів можна отримати із властивості SelectedItems. Наступний приклад перебирає список виділених компонентів і виводить кожен рядок в діалоговому вікні:

foreach (string str in listBox1.Selectedltems)

MessageBox.Show(str);

Серед Подій компонента вас можуть зацікавити SelectedIndexChanged і SelectedValueChanged, які ми вже бачили в розд. 7.3.

7.8 ListView

Представлення списку ListView- досить складний компонент і дуже потужний, тому що володіє величезними можливостями. З подібним компонентом ми працюємо практично кожен день, тому що в вікні Мій комп'ютер іконки і імена файлів відображаються за допомогою компонента цього класу.

Отже, пробіжимося по властивостям компонента:

+ View- режим відображення. Якщо розставляти властивості за алфавітом, то ми повинні були розглядати його в кінці, але я його поставив першим, тому що воно сильно впливає на роботу деяких інших властивостей. Ця властивість є перерахуванням і може приймати одне з наступних значень:

♦ Large Icon - великі іконки;

♦ Small Icon - маленькі іконки;

♦ List - маленькі іконки списком;

♦ Details - докладний режим;

♦ Tile - дозволяє відображати великі плитки;

+ Activation - реакція на введення. Тут можна вказати одне із значень:

♦ standard - реакція визначається системою за замовчуванням;

♦ OneClick- реагувати по одинарному кліка мишкою. Це означає, що подія Click буде генеруватися після одинарного кліка по елементу в списку;

♦ TwoCick - реагувати після подвійного натискання миші;

+ AllowColumnReorder - дозволяти перевизначати послідовність колонок, коли компонент відображається в режимі списку (Details);

+ AutoArrange - чи потрібно автоматично сортувати елементи списку. Опція працює У режимі маленьких або великих іконок (SmallIcon або LargeIcon);

+ CheckBoxes - дозволяє відображати прапорці checkBox навпроти кожного елементу списку;

+ Columns - дозволяє задати колонки, які будуть відображатися в докладному режимі. Виділіть цю властивість в панелі Properties і натисніть на кнопку виклику вікна редактора, який ви можете побачити на рис. 5.17. Зліва внизу вікна знаходяться кнопки Add і Remove для додавання і видалення колонки. Створені колонки з'являються в списку Members зліва, а справа можна побачити редактор властивостей виділеної колонки. Заголовок колонки можна задати у властивості Text;

+ FullRowSelect - якщо властивість рівно true, то в докладному режимі буде виділятися не тільки заголовок елементу, але і його додаткова інформація в колонках (SubItems), які ми задавали У властивості Соlumns, Тобто повністю весь рядок елементу, а не тільки заголовок;

Описание: image17

Рис. 5.17. Редактор колонок



+ Groups - ця властивість дозволяє створювати групи для елементів списку. При виклику редактора властивості з'являється вікно, схоже з редактором колонок. У вікні також будуть кнопки створення і видалення груп, а властивості групи можна побачити в правому списку. Заголовок групи можна задати у властивості Header;

+ HeaderStyle- стиль заголовків колонок. Тут можна вказати одне з наступних значень:

♦ Clickable- по заголовку колонок можна натискати як по кнопці. Найчастіше на натискання миші по заголовку вішають сортування. Якщо ви не обробляєте клацання, і вони не потрібні, то краще використовувати інше значення;

♦ Nonclickable - по заголовку не можна буде натискати як по кнопці;

♦ None - заголовок не потрібен;

+ HideSelection - заховати виділення, коли елемент управління втрачає фокус;

+ HotTracking - поміняти курсор на іконку руки при наведенні на елемент;

+ Items - тут можна створювати елементи списку. Для даної властивості з'являється редактор, зовнішній вигляд якого можна побачити на рис. 5.18.

Кожен Елемент списку - це досить складний об'єкт з безліччю властивостей. Текст, який буде призначений елементу, МОЖНА побачити У властивості Text, а У властивості Group можна вибрати Групу, в яку потрібно додати елемент. Властивість Subitems - це вбудована колекція всередині елементу колекції. Тут можна задавати додаткові елементи, які будуть відображатися в колонках, які ви могли задати у властивості columns представлення списку Listview;

Описание: image18

Рис. 5.18. Редактор елементів списку



+Label Edit- булева властивість, що визначає, чи можна редагувати заголовки елементів;

+ Label Wrap - чи можна розбивати заголовок елементів на кілька рядків, якщо його назва занадто довга;

+ LargeImageList - дозволяє задати список з іконками для великих картинок у вигляді компонента imageList, який ми поки не розглядали. Вказавши в цю властивість список картинок, ви можете призначати елементам картинки з цього списку за індексом;

+ MultіSelect - дозволити множинне виділення;

+ ShowGroups - чи потрібно відображати групи;

+ SmallImageList - дозволяє задати список з іконками маленьких картинок.

Чому для властивостей колонок, груп і елементів списку з'являється вікно редактора? Таке вікно з'являється для будь-яких властивостей не рядкових колекцій. До цього у випадаючого списку і у списку вибору ми бачили рядкові колекції, і для їх редагування досить було простого текстового редактора. Тут у нас колекції більш складних об'єктів, і для редагування їх властивостей потрібен спеціалізований редактор, який і відображається.

Як ви вже зрозуміли, елементи списку зберігаються у властивості Items. У цієї властивості є кілька перевантажених варіантів методу Add (), щоб додавати елементи в список. Найпростіший спосіб додати новий елемент-передати методу текстовий рядок, який буде встановлений в якості заголовка нового елемента:

listView1.Items.Add("Заголовок елемента");

Кожен елемент списку має клас ListViewItem, і в даному випадку елемент такого класу буде створено автоматично, і йому буде присвоєно вказаний заголовок.

Якщо потрібно налаштувати кілька властивостей нового елемента, то буде зручніше і ефективніше створити об'єкт класу ListViewItem і передати цей об'єкт методу Add (). Наприклад, як в наступному прикладі:

ListViewItem newItem = new ListViewItem("Test");

newItem.Group = listView1.Groups[0];

listView1.Items.Add(newItem);

У цьому прикладі явно створюється екземпляр класу ListViewItem. Конструктору цього класу передається рядок, який буде заголовком елемента. У другому рядку у цього ж елемента змінюється властивість Group. Група має тип ListViewGroup, і вже існуючі групи перебувають у списку властивості Groups. Щоб не вигадувати нічого складного, я просто використовую нульову групу з цього списку (сподіваючись, що вона там вже є). Тепер залишається тільки викликати метод Add () у колекції і передати йому створений і настроєний об'єкт класу ListViewItem.

А як додати групу програмно? Подивіться на наступний приклад:

// Створити групу

ListViewGroup newGroup = new ListView Group ("Група");

listView1.Groups.Add (newGroup);

// Створити елемент

ListViewItem newItem = new ListViewItem ("Test", newGroup);

listView1.Items.Add (newItem);

Створення групи схоже на створення елементів списку, тому що групи - це теж колекції. Зверніть увагу на те, як створюється на цей раз елемент списку. У цьому прикладі я передаю конструктору не тільки заголовок, а й об'єкт групи, котра була створена тільки що.

У представлення списку є можливість вибрати кілька елементів відразу. Список цих елементів знаходиться у властивості SelectedItems. Це знову ж колекція З елементів ListViewItem, і її можна переглянути за допомогою циклу foreach, наприклад:

foreach (ListViewItem item in listView1.SelectedItems)

MessageBox.Show(item.Text);

У цьому прикладі в циклі перебираються всі виділені елементи в списку і за допомогою діалогового вікна MessageBox відображаються назви елементів.

Тепер подивимося, як можна видаляти елементи зі списку:

if (listView1.Items.Count > 0)

Перш ніж видаляти елемент, потрібно переконатися, що він є. Я видаляю в цьому прикладі нульовий елемент, тому досить упевнитися, що в списку є хоча б один елемент, тобто Items.Count більше нуля. Після цього викликається метод Remove () властивості Items, якому потрібно передати елемент. Я вибираю нульовий елемент списку Items [0].

Далеко не завжди зручно видаляти елемент по об'єкту, іноді зручніше використовувати індекси. Наступний приклад видаляє 5-й елемент, попередньо перевіривши, що в списку є не менше п'яти елементів:

if (listView1.Items.Count > 5) listView1.Items.RemoveAt(5);

Для видалення використовувався метод RemoveAt (), якому передається індекс елемента.

Серед подій, які вас можуть зацікавити при роботі з компонентом, можна виділити наступні:

+ SelectedIndexChanged- подія генерується при зміні індексу виділеного елемента в представленні;

+ SearchForVirtualItem- використовується для пошуку елементів у списку, коли він знаходиться в віртуальному режимі. Цей пошук задіюється, коли ви набираєте назву елемента на клавіатурі;

+ VirtualItemsSelectionRangeChanged- генерується кожен раз, коли змінюється набір виділених елементів. Подія генерується, тільки коли компонент знаходиться в віртуальному режимі;

+ ItemActivate - виникає при активації елемента. Метод активації задається у властивостях Activation;

+ ItemCheck- подія виникає перед тим, як властивість Checked змінилася. У нього ще не було записано нового значення, але відразу після обробки події це станеться;

+ ItemChecked - генерується, коли якийсь елемент відзначається прапорцем;

+ ItemDrag- подія виникає, коли користувач починає тягнути елемент списку;

+ ItemMouseover - подія генерується, коли курсор миші рухається над поверхнею елемента списку;

+ ItemSelectionChanged- генерується при зміні виділеного елемента в списку;

+ DrawItem- подія виникає, коли потрібно перемалювати елемент. Ця подія генерується, ТІЛЬКИ коли компонент знаходиться в режимі OwnerDraw (однойменна властивість має дорівнювати true). Ви можете використовувати довільний метод малювання елементів представлення;

+ DrawSubItem- подія генерується при малюванні підлеглого елемента (Subitem);

+ DrawColumnHeader - при малюванні заголовка списку;

+ Column Click - відбулося натискання по заголовку представлення списку. Найчастіше в обробнику цієї події реалізують можливість сортування елементів представлення;

+ ColumnWidthChanged- користувач змінив ширину колонок.

У компонента є дуже потужна можливість-програміст сам може реалізувати функцію малювання елементів представлення списку. Таким чином, елементи списку можуть бути пофарбовані в будь-який колір, все залежить від того, який код ви напишете і як ви захочете намалювати елементи списку.

7.9. PictureBox

Компонент PictureBox дозволяє відображати зображення, і його частіше використовують з метою оформлення де потрібно додати якесь зображення. Основна властивість компонента - image. Якщо викликати редактор властивості, то з'явиться вікно, яке ми вже бачили при розгляді роботи з іконкою (див. Рис. 5.13).

Ви можете вказати положення картинки на диску або в Інтернеті. В цьому випадку картинка не потрапить в файл ресурсів, а залишиться на тому місці, де і була. У компоненті буде тільки посилання на файл, яку ви повинні вказати у властивості ImageLocation. Компонент завантажить зображення після завантаження програми.

Я рекомендую вказувати завжди відносні шляхи до файлів, якщо ви хочете поставляти їх разом з програмою. Наприклад, не потрібно вказувати повний шлях до файлу типу C: \ projects \ myprogram \ image.jpg. Коли користувач встановить у себе вашу програму, у нього скоріше за все не буде такого ж шляху, а створювати його і копіювати туди файл під час установки програми - це самогубство. Вашу програму зітруть відразу ж.

Щоб цього не сталося, найпростіший спосіб-поміщати файли в ту ж папку, що і виконуваний файл, а у властивості ImageLocation вказувати тільки ім'я файлу, без шляху.

Якщо ви вкажете посилання на зображення в Інтернеті, то її завантаження потребуватиме часу після старту програми. Щоб компонент відображав на час завантаження хоч щось, ви можете вказати початкову картинку в властивості InitialImage. Якщо картинка не буде завантажена з яких-небудь причин (наприклад, немає доступу до сайту, де лежить картинка), то буде відображена картинка з властивості ErrorImage.

Є ще одна властивість, яка вам може стати в нагоді, - SizeMode. Це перерахування, яке дозволяє вибрати одне з наступних значень:

+ Stretch Image - розтягнути картинку поверх всієї поверхні компонента;

+ AutoSize - компонент автоматично прийме розміри картинки, щоб вона

була видна повністю;

+ CenterImage - відцентрувати картинку всередині компонента;

+ Zoom- зменшити картинку так, щоб вона вписувалася в компонент, при цьому пропорції зображення зберігаються;

+ Normal - просто відобразити картинку, не розтягуючи її.

 

7.10ProgressBar

Під час виконання тривалої дії дуже важливо показати користувачеві, що програма не зависла, а виконує запитані дії. Коли ви копіюєте або завантажуєте з Інтернету якийсь великий файл, то система відображає інформаційне вікно, В якому біжить індикатор процесу ProgressBar.

У цього компонента є три цікавих властивості:

+ Maximum- максимальне значення індикатора, за замовчуванням рівне 100;

+ Minimum- мінімальне значення індикатора, за замовчуванням дорівнює 0;

+ Value - поточне значення.

Створіть новий додаток і помістіть на форму компоненти ProgressBar і кнопку. Ніякі властивості міняти не будемо, а просто створіть подія click для кнопки і в ньому напишіть:

for (int i = 0; i < 100; i++)

{

progressBar1.Value = i;

Thread.Sleep(lOO);

}

У прикладі запускається цикл, який виконується від 0 до 100. Всередині циклу просто присвоюємо властивості value компонента PogressBar чергове значення змінної i, яка збільшується на 1 на кожному кроці. Щоб цикл працював не дуже швидко, в нього додано рядок з викликом статичного методу sleep про класу Thread, яка створює затримку на передане в якості параметра значення в мілісекундах.

7.10RadioButton

Компонент  дуже схожий на checkBox і дозволяє користувачеві вибирати цей компонент, але тільки один із компонентів RadioButton на контейнері може бути виділений. Під контейнером розуміється будь-який компонент, на поверхні якого можна розташувати інші компоненти. Ми поки працюємо тільки з формами, тому на формі може бути виділений тільки один з компонентів класу RadioButton.

Основні властивості компонента- це, звичайно ж, Text, де ви повинні задавати текст, який буде відображатися на компоненті, і checked, яке вказує на те, виділений компонент чи ні.

Створіть новий додаток і помістіть на його форму три компонента класу RadioButton. Відкрийте програму і спробуйте поклацати по ним. Вибір з одного компонента переходить на інший автоматично. Вам не потрібно знімати виділення з поточного компонента, перш ніж вибирати новий.

5.7       TextBox

Цей компонент призначений для введення даних користувачем. Якщо вам потрібно, щоб користувач ввів рядок, число або ще щось, ми найчастіше будемо встановлювати на форму саме цей компонент. У нього не так вже й багато значущих властивостей:

+ Text - містить текст, який відображається в компоненті. Ви можете прочитати дані, які ввів користувач, або навіть встановити щось у властивості;

+ Multiline - дозволити багаторядкове відображення даних;

+ UseSystemPassword- введений текст буде ховатися за крапками, як при введенні пароля.

У компонента всього пара цікавих подій. Перше з них-TextChanged, яке генерується кожен раз, коли користувач змінив текст в компоненті.

Ще одна властивість, яка може стати в нагоді вам, - Modified. Значення властивості автоматично змінюється на true, якщо користувач вніс якусь зміну в текст компонента. Скинути значення на false можна тільки вручну. Наприклад, за допомогою наступного обробника події ModifiedChanged ми відображаємо в мітці label2 стан компонента:

private void lastnameTextBox_Modif iedChanged(object sender, EventArgs e)

{

if (lastnameTextBox.Modified) label2.Text - "Изменен"; else

label2.Text = "Сохранен";

}

Щоб скидати властивість Modified в false, можна додати на форму кнопку і на її натискання написати:

lastnameTextBox.Modified = false;

Тепер якщо внести зміну в текст, то властивість Modified змінюється на true, а після натискання кнопки властивість буде змінюватися на false.

7.13    TreeView

Останній компонент з розряду загальних, який ми тут розглянемо, - це TreeView, який дозволяє вибудовувати інформацію у вигляді дерева. Який приклад дерева можна привести? А ось, наприклад, в панелі Solution Explorer структура проекту побудована у вигляді дерева.

Найцікавіші з властивостей компонента TreeView:

+ CheckBoxes - відображати прапорці, щоб можна було позначати елементи дерева;

+ HideSelection - ховати виділення, коли елемент управління втрачає фокус;

+ HotTracking - якщо властивість рівно true, то елементи підкреслюються і підсвічуються синім, коли курсор рухається над ними;

+ LabelEdit - визначає, чи дозволено редагувати заголовки елементів дерева;

+ Nodes - колекція, в якій знаходяться всі елементи дерева. При відкритті вікна редагування цієї властивості ви побачите редактор, як на рис. 5.19. Зверніть увагу, що зліва внизу знаходяться кнопки Add Root і Add Child. Перша кнопка створює кореневий елемент, а друга створює дочірній елемент по відношенню до виділеного. Елементи будуть додаватися у вигляді дерева в лівій області, і ви можете в ній перетягувати елементи, як завгодно, щоб побудувати-ить необхідне дерево;

Описание: D:\!C#\media\image19.jpeg

Рис. 5.19. Редактор елементів списку дерева



+ ShowLines - чи потрібно показувати лінії між елементами;

+ Show Plus Minus - відображати поруч із елементами, що містять дочірні елементи, хрестик для розкриття гілки. Це може бути непотрібним, якщо ви призначили елементам картинки і тоді ці хрестики можуть псувати вигляд;

+ ShowRootLines - чи потрібно показувати хрестик і лінії у кореневого елемента.

Давайте створимо додаток і кинемо на нього компонент дерева. Тепер покладемо на нього ще три кнопки: Додати кореневий елемент, Додати дочірній елемент і Видалити елемент. При натисканні першої кнопки пишемо наступний код:

TreeNode newNode = new TreeNode("кореневий елемент "); treeView1.Nodes.Add(newNode);

У першому рядку ми оголошуємо змінну класу TreeNode і инициализируем її. Що це за клас? Це клас елементів дерева. Заголовок елемента я передав в якості параметра конструктору при ініціалізації, хоча можна було написати і так:

TreeNode newNode = new TreeNode();

newNode.Text = "кореневий елемент ";

У цьому прикладі спочатку ініціалізується змінна newNode конструктором за замовчуванням, а потім встановлюється властивість Text.

Щоб додати кореневий елемент дерева, потрібно викликати метод Add () властивості Nodes компонента дерева. Пам'ятайте, ми викликали редактор саме властивості Nodes з панелі Properties при роботі з компонентом візуально.

Метод Add () має безліч перевантажених варіантів для вашої зручності. Можете використовувати той, який більше подобається або який краще підходить до конкретної ситуації. Наприклад, додати кореневий елемент можна було і одним рядком коду:

treeView1.Nodes.Add("кореневий елемент ");

У цьому випадку метод сам створює екземпляр класу TreeNode для зберігання елемента дерева і присвоїть йому заголовок, який ви передали методу. Цей варіант використовується в тих випадках, коли вам не потрібно десь додатково зберігати змінну об'єкта елемента дерева або виконувати додаткових маніпуляцій з елементом.

А як додати дочірній елемент до вже існуючого кореню? Як взагалі зберігаються дочірні елементи? Якщо кореневі елементи зберігаються у вигляді колекції прямо в властивості Nodes компоненти дерева, то дочірні елементи зберігаються у своїх батьківських елементів у властивості Nodes. Подивимося на наступний приклад:

if (treeViewl.SelectedNode != null)

treeView1.SelectedNode.Nodes.Add("дочірній елемент");

У властивості SelectedNode компоненти TreeView зберігається виділений елемент дерева. Ця властивість має тип TreeNode з усіма наслідками, що випливають звідси наслідками.

В даному прикладі я спочатку перевіряю властивість SelectedNode на нульове значення. Заведіть і собі в звичку, перш ніж звертатися до властивостей об'єктної змінної, яку ви самі явно не ініціалізували, завжди перевіряти її на нульове значення. В даному випадку, якщо в дереві Нічого не вибрано, то властивість може дорівнювати нулю, і спроба звернутися до Nodes призведе до збою. Я застрахував нас від збою, тому для додавання дочірнього елемента по відношенню до виділеного МИ можемо викликати метод Add () властивості Nodes об'єкта SelectedNode. Цей метод також має безліч перевантажених варіантів, і йому теж можна було передати заздалегідь створений екземпляр класу TreeNode.

У нас на формі залишилася ще одна кнопка для видалення елемента. Давайте напишемо для неї код:

if (treeView1.SelectedNode != null) treeView1.SelectedNode.Remove();

Спочатку вже за звичкою перевірити властивість SelectedNode на нульове значення, І якщо воно не нульове, ТО викликається метод Remove (), який видаляє поточний елемент. Якщо у нього є дочірні елементи, то вони зникнуть разом зі своїм батьком.

Якщо ви хочете видалити тільки дочірні елементи, не чіпаючи їх батьків, то можна виконати наступний рядок:

treeView1.SelectedNode.Nodes.Clear();

Як ми вже знаємо, дочірні елементи знаходяться у властивості Nodes, і саме у цієї властивості є методи додавання нових дочірніх елементів і метод Clear () для очищення. Властивість Nodes - містить елементи з усіма витікаючими наслідками, тобто все, що ми говорили раніше і будемо говорити в майбутньому про колекції, буде зачіпати і цю властивість.

Колекції схожі з масивами, і для доступу до заголовку нульового кореневого елемента дерева потрібно написати: treeView1.Nodes [0] .Text, а для доступу до першого елементу: treeView1.Nodes [1] .Text (на рис. 5.19 це Кореневий елемент 2 ).

Для доступу до нульового дочірнього елемента нульового кореневого елемента потрібно вже написати: treeView1. Nodes [0] .Nodes [0] .Text, і т. д., вглиб по гілках нашого дерева.

А що якщо потрібно переглянути елементи дерева, наприклад, для збереження їх в файл або для пошуку в дереві? Тут добре підходить класична задача рекурсивного виклику. Давайте подивимося, як це реалізувати в вигляді коду. Наступний метод приймає як параметр шлях і колекцію елементів:

void ViewCollection(string caption, TreeNodeCollection collection)

{

if (caption != "") caption +=’-‘;

foreach (TreeNode node in collection)

{

if (node.Nodes.Count > 0)

ViewCollection(caption + node.Text, node.Nodes); else

MessageBox.Show(caption + node.Text);

}

}

Щоб переглянути дерево з самого початку, цей метод можна викликати наступним чином:

ViewCollection("", treeView1.Nodes);

Перший параметр - порожній рядок, тобто, початковий шлях порожній. Другий параметр - елементи з властивості Nodes, де зберігаються кореневі елементи дерева.

Усередині методу спочатку перевіряємо, якщо поточний зміст змінної caption не порожнє, то додаємо роздільник у вигляді знака тире.

Так як колекція схожа з масивом, то ми можемо перебирати її за допомогою циклу foreach. Кожен елемент колекції має ТИП TreeNode, і це ми вже знаємо. Всередині циклу перевіряємо, якщо у поточного елемента є дочірні елементи, ТО рекурсивно викликаємо метод ViewCollection () для перегляду цих дочірніх елементів. При цьому значення першого параметра збільшуємо на значення заголовка поточного елемента. Якщо дочірніх елементів немає, то виводиться повідомлення, В якому відображається вміст змінної caption плюс ім'я поточного елемента.

Таким чином, метод буде перебрати всі елементи дерева в пошуках кінцевих пунктів. У процесі пошуку через змінну caption накопичується повний шлях до цих кінцевих елементів.

У дерева найцікавішими є такі події:

+ AfterCheck- виникає, коли користувач ставить прапорець або прибирає його з якогось елементу дерева. У обробника події друга властивість має тип TreeViewEventArgs. У цього класу є властивість Node, в якому зберігається позначений елемент дерева:

private void treeView1_AfterCheck(object sender, TreeviewEventArgs e)

{

MessageBox.Show(e.Node.Text);

}

+ After Collapse - виникає, коли користувач звернув будь-яку гілку дерева. Другий параметр має тип TreeviewEventArgs, властивість Node якого містить згорнутий елемент дерева;

+ After Expand- виникає, коли користувач розгорнув якусь гілку дерева. Другий параметр має ТИП TreeviewEventArgs, ВЛАСТИВІСТЬ Node якого містить згорнутий елемент дерева;

+ AfterLabelEdit - подія виникає, коли користувач завершив редагування заголовка елемента дерева. Другий параметр події має тип Node- LabelEditEventArgs, який має такі цікаві властивості:

CancelEdit - якщо встановити властивість в false, то зміни будуть скасовані;

Label - новий текст, який повинен бути призначений елементу;

Node - тут присутній елемент дерева, заголовок якого змінюється;

+ AfterSelect- подія виникає, коли користувач вибирає який-небудь елемент в дереві.

Тут потрібно зупинитися і помітити, що для всіх описаних подій є двійники, які викликаються перед виникненням події. Наприклад, для події AfterSelect є двійник З Ім'ям BeforeSelect, який генерується перед тим, як змінити виділений елемент. Тобто в обробнику події BeforeSelect у властивості SelectedNode буде перебувати ще старий елемент дерева, який був виділений раніше.

+ DrawNode - подія спрацьовує при необхідності намалювати якийсь елемент дерева. Подія генерується, тільки коли дерево знаходиться в режимі OwnerDraw;

+ NodeMouseClick - виникає, коли користувач клацнув по елементу дерева. Другий параметр події має тип TreeNodeMouseClickEventArgs, і через його властивості Node і Button ми можемо дізнатися, за яким елементу дерева клацнули і якою кнопкою миші;

+ NodeMouseDoubleclick- виникає, коли користувач двічі клацнув по елементу дерева. Другий параметр події має тип TreeNodeMouse- ClickEventArgs з усіма витікаючими наслідками;

+ NodeMouseHover - виникає, коли курсор миші рухається над яким-небудь елементом.

8. Контейнери

Контейнери - це компоненти, на поверхні яких ви можете розміщувати інші елементи управління. Смислового навантаження з точки зору програмування в них мало, тут в основному нас цікавлять можливості оформлення й угруповання інших компонентів.

Наприклад, ми вже знаємо, що компоненти RadioButton, розташовані на поверхні одного контейнера, працюють в групі. При виборі одного з них знімається виділення з іншого компонента, тобто в один момент може бути виділений ТІЛЬКИ ОДИН компонент RadioButton на поверхні контейнера. До цього ми працювали тільки з одним контейнером - формою, але тепер познайомимося і з іншими.

8.1 GroupBox

Якщо вже ми торкнулися теми угруповання компонентів RadioButton, то слід відразу подивитися на компонент GroupBox, який вирішує цю задачу дуже добре. Приклад компонента можна побачити на рис. 5.20. У компонента є властивість Text, яке відповідає за текст, який відображається в заголовку групи. По краю компонента йде контур, щоб користувач бачив межі компоненту.

На поверхні компонента ви можете розташувати свою групу компонентів RadioButton, і вони будуть працювати незалежно.

Описание: C:\!!C#\media\image20.jpeg

Рис. 5.20. Використання компонента GroupBox



8.2 Panel

Напевно, це самий популярний контейнер, який програмісти використовують для оформлення та угруповання, і у якого немає ніякого тексту, та й не потрібно йому нічого.

Створіть новий додаток і помістіть на форму панель. Встановіть у неї властивість Dock на Left, щоб панель простяглася вздовж лівого краю вікна. Тепер помістіть на форму (саме на форму, а не на панель) компонент RichTextBox і у нього змініть властивість Dock на Fill, щоб компонент влився у все область вікна. Усередині панелі зліва можна розміщувати якісь елементи управління, за допомогою яких користувач буде працювати з RichTextBox.

8.3 TabControl

Зміст компонента- ті ж панелі, які можна перемикати за допомогою вкладок (tab), розташованих вгорі компонента. Створіть додаток і перетягніть на нього компонент TabControl. За замовчуванням буде створений компонент з двома сторінками з іменами tabPage1 і tabPage2.

Клацаючи по заголовкам вкладок просто в дизайнера форми, ви можете перемикати виділену в даний момент сторінку. Клацаючи в центрі сторінки, ви можете вибирати елемент управління сторінки. Сам компонент сторінок має тип TabControl, а сторінки всередині нього мають тип TabPage. Якщо ви хочете виділити сам елемент управління, то можна клацнути по верху компонента, де розташовані вкладки.

Самі сторінки класу TabPage практично не відрізняються за властивостями від панелей, тільки мають властивість Text, яке зберігає заголовок сторінки. Є ще властивість ToolTopText, в якому можна вказати текст підказки для сторінки.

Компонент Tabcontrol набагато цікавіший, і у нього є цікаві властивості:

+ HotTrack - вкладки будуть змінювати своє оформлення (як би підсвічуватися), коли ви наводите на них курсор миші;

+ Multiline- заголовки вкладок можуть розташовуватися в кілька рядків, якщо

вони не поміщаються в один рядок;

+ ShowToolTips - відображати підказки сторінок;

+ TabIndex - індекс активної сторінки;

+ TabPages - в цій властивості знаходиться колекція сторінок.

Дуже часто буває необхідно, щоб елемент управління з TabControl відображав за замовчуванням саме першу сторінку. На практиці відображається та сторінка, яка була відкрита у вас в дизайнері, коли ви компілювали проект. Це означає, що після зміни вмісту другої і наступних сторінок потрібно не забувати повернутися на першу сторінку, перш ніж компілювати проект. Але як на зло, дуже часто забуваєш це зробити.

Щоб не тримати в пам'яті необхідність повернутися на першу сторінку, можна переключитися у код і після виклику методу InitializeComponent () в конструкторі форми прописати установку індексу активної вкладки: public Form1 ()

{

InitializeComponent();

tabControl1.Tabindex =0; // явно встановити індекс вкладки

}

Дизайнер пропише установку вкладки, яку ви вибрали в дизайнері, всередині методу InitializeComponent (), а ви після цього перепризначити значення властивості на своє.

8.4 FlowLayoutPanel і TableLayoutPanel

Ці два компоненти схожі за призначенням. Їх головне завдання - вирівнювання компонентів, які ви кидаєте поверх панелі. Панель FlowLayoutPanel автоматично вирівнює компоненти в лінію. Спробуйте кинути на її поверхню кілька міток, вони автоматично вишикуються один за одним.

Компонент TableLayoutPanel вирівнює Компоненти у вигляді таблиці. У властивостях Column Count і Rowcount ви можете вказати кількість колонок і рядків в таблиці відповідно.

Властивості Columns і Rows - це колекції, в яких знаходяться параметри колонок і рядків. Виділіть властивість Columns або Rows і викличте його редактор, і ви побачите вікно, як на рис. 5.21. Це вікно не просто однакове для обох властивостей, це одне й те саме вікно, просто у верхній частині вікна є список, що випадає Show, в якому ви можете вибирати, що саме зараз відображати - параметри рядків або колонок.

Описание: image21

Рис. 5.21. Редактор властивостей колонок і рядків



Виділяючи рядок і колонку в лівому списку, праворуч ви можете задати її розмір в абсолютних значеннях (Absolute) або в відносних (Percent). Якщо розмір не має значення, то можна вибрати AutoSize, щоб система пропорційно поділила простір. Зліва внизу є кнопки для додавання в кінець списку, видалення і вставки в поточну позицію нового рядка / колонки.

У табличній панелі є ще одна цікава властивість - Grows type, яке визначає, в який бік повинна зростати таблиця, коли ви додаєте нову клітинку в момент, коли всі клітинки зайняті. За замовчуванням стоїть значення AddRows, тобто в таблиці буде додано новий рядок. Можна також вказати AddColumns, щоб додавалася колонка, або FixesSize - не можна додавати нову клітинку.

9.     Меню і панелі інструментів

Меню, панелі і смужки стану є невід'ємною частиною більшості додатків. Без меню можна обійтися, якщо ваш додаток виконує всього дві-три дії, які можна оформити просто в вигляді кнопок на поверхні головної форми. Навіть в тих випадках, коли програма виконує всього пару команд, програмісти все ж вважають за краще створювати в вікні меню, тому що це естетично і просто зручно.

Користувачі звикли шукати потрібні команди в меню, тому що це зручно і по іменах легко знайти потрібну команду. Команди в ньому згруповані за категоріями, і якщо програміст добре продумав меню і коректно назвав їх пункти, то користувач зможе розібратися з роботою програми без додаткової документації. У таких випадках дуже часто говорять, що програма має інтуїтивно зрозумілий інтерфейс, а це величезний плюс вашому додатку.

Компоненти, які ми будемо розглядати далі, знаходяться в розділі Menus & Toolbars панелі Toolbox.

9.1 MenuStrip

Почнемо розгляд з меню. Створіть новий додаток і помістіть на його форму компонент MenuStrip. Уздовж верхньої кромки вікна під його заголовком буде розтягнута панель меню. У мене цей компонент отримав назву menustrip1. Виділіть форму і зверніть увагу, що у властивості MainMenuStrip з'явилося ім'я нашого компонента меню. Так як ні одного меню ще не було на формі, то дизайнер взяв на себе сміливість, а може бути і нахабство, призначити новий компонент в якості головного меню форми.

Якщо виділити компонент, то зліва з'являться світлий прямокутник і сірий напис всередині "Туре Неrе" (Надрукуйте тут). Якщо клацнути по цьому прямокутнику, то в ньому з'явиться маленьке поле введення, в якому можна ввести ім'я нового пункту меню. введіть «Файл» і натисніть клавішу <Enter>. Зверніть увагу, що тепер і знизу від нашого пункту меню і справа знову з'явилися прямокутники з написом "Туре Неrе" (рис. 5.22).

Клацнувши на прямокутнику знизу, можна створити пункт підменю, а якщо клацнути праворуч, то можна створити ще один розділ меню. Таким чином, можна створювати структуру програмного меню. Спробуйте навести мишкою на прямокутник, але не клацати по ньому. В прямокутнику з'явиться кнопка списку, після натискання на яку з'явиться спливаюче меню з елементами, які ви можете додати в компонент меню. Тут у нас є можливість працювати з такими компонентами:

+ MenuItem - елемент меню, який створюється за замовчуванням;

+ ComboBox-випадаючий спмсок Так, ви можете додавати в якості елементів меню навіть випадаючий список, хоча це робиться дуже рідко;

+ Separator- смуга, яка розділяє підменю на групи. Тут потрібно зробити акцент на підменю, тому що роздільник неможливо створити для основних розділів меню;

+ TextBox - поле введення теж може бути впроваджено просто в меню.

Описание: image22

Рис. 5.22. Редактор меню



Якщо двічі клацнути по будь-якому пункту меню, то дизайнер створить обробник події за замовчуванням, яким буде подія click. Ця дія рівносильна виділенню пункту меню в дизайнері, переходу на вкладку подій в панелі властивостей і створення обробника для події Click.

Давайте створимо меню Вихід, двічі клацаємо по ньому і в створеному обробнику події напишемо виклик методу Close ():

private void ToolStripMenuItem_Click(object sender, EventArgs e)

{

Close();

}

Метод close () форми призводить до закриття вікна. Якщо це головне вікно програми, то за його закриття переривається і головний обробник подій (він створюється додатком непомітно для нас), що призведе до завершення роботи програми.

Що цікавого є у пунктів меню? По перше, потрібно розуміти, що вони походять від класу ToolStripMenuItem і успадковують його властивості та методи. Найбільш цікаві властивості наступні:

+ Checked- логічне значення, яке вказує, чи поставлено прапорець check у

меню. Якщо меню відмічене, то зліва від імені з'являється прапорець, як у CheckВох;

+ CheckOnClick- це властивість вказує на те, що при виборі меню значення параметра checked буде змінюватися на протилежне;

+ CheckState - ідентично за призначенням з однойменною властивістю у CheckBox;

+ DisplayStyle- стиль відображення пункту меню. Тут можна вибрати одне із значень:

♦ ImageAndText - картинка і текст;

♦ image - картинка;

♦ Text - текст;

♦ None - нічого;

+ DropDownItems- колекція, в якій знаходяться елементи підменю для поточного пункту. Ви можете редагувати меню не тільки візуально, але і викликавши редактор цієї властивості;

+ Image - картинка для пункту меню;

+ Image Align - в який бік повинна бути вирівняна картинка;

+ Image scaling - чи потрібно розтягувати картинку, щоб вона заповнила весь простір, виділений під неї, якщо картинка менше або більше;

+ ImageTransparent - колір прозорості. Найчастіше середовище розробки саме правильно визначає колір, який повинен бути прозорим;

+ Shortcut Keys - в цій властивості ви можете задати поєднання клавіш, які будуть викликати пункт меню. Ви можете написати поєднання клавіш руками в поле введення властивості або клікнути на кнопку виклику випадаючого вікна і в ньому вибрати букву і кнопку модифікатора;

+ ShowShotcutKeys - чи потрібно відображати в меню призначене поєднання клавіш.

Для всіх пунктів меню, в тому числі і контекстних, які ми будемо розглядати в розд, 9.2, найцікавішою подією, звичайно ж, є Click, яка виникає, коли користувач клікнув по елементу меню. Крім цього вам можуть стати в нагоді події CheckedChanged І CheckStateChanged, які виникають, коли користувач поставив прапорець (змінив властивість changed) або змінив властивість CheckState відповідно.

9.2            ContextMenuStrip

Контекстне меню з'являється у відповідь на натискання правою кнопкою миші на певному елементі управління або формі. В .NET за контекстне меню відповідає клас ContextMenuStrip. Помістіть компонент на форму, і вгорі форми з'явиться візуальний редактор для пунктів меню, схожий на редактор головного меню, але тут ви можете створювати тільки підпункти, але не розділи.

Спробуйте виділити якийсь елемент управління на формі або саму форму, і з форми зникне не тільки редактор контекстного меню, а й саме контекстне меню. Це тому, що воно не візуальне. Невізуальні компоненти з'являються на спеціальній панелі під формою (рис. 5.23). Щоб знову відобразити візуальний редактор меню, потрібно виділити відповідний компонент контекстного меню на спеціальній панелі.

Створення контекстного меню ідентично створення пунктів головного меню. Створюються елементи одного і того ж класу - ToolStripMenuItem, тому немає сенсу повторюватися і знову розглядати його властивості.

Як тепер використовувати контекстне меню? Виділіть компонент або форму, якому ви хочете призначити меню. Знайдіть властивість ContextMenuStrip і виділіть її. Клацніть по кнопці виклику списку в редакторі властивостей, і в ньому ви побачите ім'я створеного компонента контекстного меню. Виберіть його. Більше нічого робити не потрібно. Можете запустити додаток, натиснути правою кнопкою по компоненті або формі і переконайтесь, що контекстне меню з'являється.

Описание: image23



Рис. 5.23. Контекстное меню

 

9.3 ToolStrip

Панелі ToolStrip найчастіше дублюють функції, які вже є в меню, надаючи користувачу можливість швидко викликати команду. Для зручного створення меню найкраще використовувати компонент класу ToolStrip.

Створіть новий додаток І перетягніть на нього компонент ToolStrip. Цей компонент за замовчуванням буде розтягнутий вздовж верхнього краю вікна. Коли панель виділена в редакторі, то зліва з'являється спеціалізована кнопка, яка існує віртуально, і містить невелику стрілку для виклику меню, що випадає (рис. 5.24).

Рис. 5.24. редактор панелі

При натисканні на самій віртуальній кнопці буде створена кнопка класу ToolStripButton на поверхні панелі. Якщо викликати меню, що випадає, то в ньому ви можете вибрати тип створюваного компонента на поверхні панелі. Ви можете створити такі типи компонентів:

+ Button - кнопка;

+ Label - мітка;

+ Split Button- кнопка, яка має додаткову кнопку для виклику спливаючого меню. Основна та додаткова кнопки працюють незалежно;

+ DropDownButton - кнопка, яка викликає спливаюче меню. Спливаюче меню з'явиться саме після натискання кнопки, без натискання будь-яких додаткових кнопок;

+ Separator- роздільник, який дозволяє логічно розділяти групи кнопок;

+ ComboBox - випадаючий список;

+ TextBox - текстове поле введення;

+ ProgressBar - індикатор процесу.

Створювана кнопка ToolstripButton (кнопки такого класу створюються на панелі ToolStrip) дуже схожа за властивостями з кнопкою Button, яку ми вже розглядали, ТІЛЬКИ У неї є властивость Checked, CheckOnClick І CheckState, як у пункту меню і у компонента CheckBox, щоб кнопку можна було не просто натискати, а й змінювати стан - утоплювати і відпускати. Коли властивість CheckOnClick рівно true, то при натисканні кнопка залипає, змінюючи стан checked на true, а при повторному натисканні кнопка відпускається, змінюючи checked на false. В іншому випадку при натисканні кнопка натискається і тут же відпускається.

Інші компоненти, які ви можете створити на поверхні панелі, ідентичні схожим компонентам, які ми розглядали раніше. Наприклад, SplitButton і DropDownButton схожі за властивостями на класичну кнопку, просто у них є додаткова можливість у вигляді жорстко прив'язаного меню, і при виділенні кнопки в редакторі з'являється редактор для цього меню.

Компоненти ComboBox, TextBox і ProgressBar ідентичні стандартним компонентом, які ми розглядали в розд. 7.

9.4            StatusStrip

Рядок стану, як випливає з назви, призначений для того, щоб відображати стан роботи програми. Рядок стану (StatusStrip) сам по собі нічого особливого собою не представляє. Найцікавіше знаходиться всередині цього компонента, на поверхні якого ви можете створювати компоненти, які і будуть виконувати якусь функцію. Наприклад, компонент типу мітки може відображати текстову інформацію.

Коли компонент рядка стану виділено, то зліва з'являється невелика кнопка, після натискання якої створюється мітка класу ToolStripStatusLabel, схожа на мітку Label і також призначена для відображення інформації. Якщо потрібно створити компонент іншого класу, то можна маленькою кнопкою зі стрілкою відкрити спливаючий список опцій, в якому можна знайти додаткові елементи:

+ Status Label - мітка;

+ ProgressBar - індикатор процесу;

+ Split Button- кнопка, яка має додаткову кнопку для виклику спливаючого меню. Основна та додаткова кнопки працюють незалежно;

+ DropDownButton - кнопка, яка викликає спливаюче меню. Спливаюче меню з'явиться саме після натискання кнопки, без натискання на будь-які додаткові кнопки.